Correct way to close WCF 4 channels effectively - c#

I am using the following ways to close the WCF 4 channels. Is this right way to do it?
using (IService channel
= CustomChannelFactory<IService>.CreateConfigurationChannel())
{
channel.Open();
//do stuff
}// channels disposes off??

That used to be the commonly accepted way to release WCF client proxies in the "early" days of WCF.
However things have since changed. It turned out that the implementation of IClientChannel<T>.Dispose() simply invokes the IClientChannel<T>.Close() method, which may throw an exception under some circumstances, such as when the underlying channel isn't open or can't be closed in a timely fashion.
Therefore it's not a good idea to invoke Close() within a catch block since that may leave behind some unreleased resources in case of an exception.
The new recommended way is to invoke IClientChannel<T>.Abort() within the catch block instead, in case Close() would fail. Here's an example:
try
{
channel.DoSomething();
channel.Close();
}
catch
{
channel.Abort();
throw;
}
Update:
Here's a reference to an MSDN article that describes this recommendation.

Although not strictly directed at the channel, you can do:
ChannelFactory<IMyService> channelFactory = null;
try
{
channelFactory =
new ChannelFactory<IMyService>();
channelFactory.Open();
// Do work...
channelFactory.Close();
}
catch (CommunicationException)
{
if (channelFactory != null)
{
channelFactory.Abort();
}
}
catch (TimeoutException)
{
if (channelFactory != null)
{
channelFactory.Abort();
}
}
catch (Exception)
{
if (channelFactory != null)
{
channelFactory.Abort();
}
throw;
}

Related

Continue after try-catch-finally

This might sound like a weird question but I don't get it...
Let's say I have an application which connects to a server to do some stuff. This connect might fail and throw an exception which I can catch.
try {
Client.connect();
} catch (System.Exception ex) {
// Do some exception handling...
} finally {
// Do some cleanup...
}
However, in case that the connect is succcesful the application shall continue...
try {
Client.connect();
} catch (System.Exception ex) {
// Do some exception handling...
} finally {
// Do some cleanup...
}
// Talk to the server...
The "server talking" however is executed in any case. It doesn't matter if the exception occured or not.
How can I make sure that the "server talking" is only executed if the connect was successful? Do I have to move all of the following code inside the trystatement? What is a clean way to program such a behavior?
"Talk to the server" should happen in the try block, right after
Client.connect();
The easiest way is to just set a boolean. But there are many many many ways to deal with this.
bool connectionError = false;
try {
// connect
} catch (...) {
connectionError = true;
} finally {
// whatever
}
if (!connectionError) {
// talk to server.
}
Have another variable like clientConnected and set it to true right after Client.Connect(). Then outside the try-catch check for clientConnected before talking to the server.
Avoid doing everything in a single try-catch. You should use separate try-catch blocks for different actions that might throw exceptions, and catch specific exceptions as much as possible.
Typically you use try...catch statements for those statements which you expect to throw an Exception. Try...Catch defines its own scope, so you should declare any variables outside of the Try...Catch block (at least, those variables that you want to use outside of it).
If you want to know if an exception was thrown, then define the Exception variable above the Try...Catch. You can then examine it to determine if it is Null or not.
System.Exception ex;
try {
Client.connect();
} catch (ex) {
// Do some exception handling...
} finally {
// Do some cleanup...
}
if (ex != null){ ... }
// Talk to the server...
You could log an event and then call some code to either try again or to cancel... or whatever you need to do.
Use some type of flag variable to indicate whether server is connected or not. If your method is returning a boolean variable then also it is ok.
int flag=0;
while(flag==0){
try {
Client.connect();
flag=1;
} catch (System.Exception ex) {
// Do some exception handling...
} finally {
// Do some cleanup...
}
}
//If server connects code

How to rethrow a prior exception from inside a nested try-catch block? (C#)

I have code that attempts a type conversion. If it fails, I want to try something else, and if that also fails, then rethrow the original exception attempted by the first conversion. The problem is that the only way I know of to rethrow is to have 'throw;' sitting at the end of the catch block. What happens when I only want the rethrow to happen from within another catch block?
try
{
valueFromData = Convert.ChangeType(valueFromData, pi.PropertyType);
}
catch(InvalidCastException e)
{
Debug.WriteLine(String.Concat("Info - Direct conversion failed. Attempting to convert using String as an intermidiate type."));
try { valueFromData = Convert.ChangeType(valueFromData.ToString(), pi.PropertyType); }
catch { throw e; }
}
As you can see above, I have to use 'throw e;', which resets the call stack.
Only workaround I've though of so far is (imo) gross:
bool handled = true;
...
catch { handled = false; }
if( !handled ) throw;
There is no way to rethrow an exception from an outer catch block inside an inner catch block. The best way to achieve this pattern is to note whether or not the inner operation succeeded
catch (InvalidCastException e) {
bool threw = false;
try {
...
} catch {
threw = true;
}
if (threw) {
throw;
}
}
If you are intending to make multiple attempts at conversion then it certainly makes sense to use non-throwing operations where applicable so that you sidestep the problem entirely.
Supposing that's not possible for the sake of argument, the next step is to question the throw e; approach. In the example code you give, IMHO there is no problem at all if your throw resets the call stack. Once someone gets to the source code for this method (which the modified call stack would still point to), I think it's pretty obvious what's going on. So while resetting the call stack is always a questionable decision, in this particular case it should be allowed to happen because there would be no tangible drawback.
Finally, the workaround you mention is interesting as well as gross (agree on that!).
I tried the following and it seems to achieve your goal, when the 2nd exception occurs (in this case, the ArgumentException) it throws the first exception (InvalidCastException)
[TestMethod]
[ExpectedException(typeof(InvalidCastException))]
public void ReThrowException() {
var ret = false;
try {
ret = F1(1);
}
catch (InvalidCastException ex) {
try {
ret = F1(2);
}
catch (Exception e) {
Debug.WriteLine(e.Message);
throw ex;
}
}
}
private bool F1(int i) {
if (i == 1) {
throw new InvalidCastException();
} else {
throw new ArgumentException();
}
return false;
}
Hope this helps,
Alan.

CA2000 and disposal of WCF client

There is plenty of information out there concerning WCF clients and the fact that you cannot simply rely on a using statement to dispose of the client. This is because the Close method can throw an exception (i.e. if the server hosting the service doesn't respond).
I've done my best to implement something that adheres to the numerous suggestions out there.
public void DoSomething()
{
MyServiceClient client = new MyServiceClient(); // from service reference
try
{
client.DoSomething();
}
finally
{
client.CloseProxy();
}
}
public static void CloseProxy(this ICommunicationObject proxy)
{
if (proxy == null)
return;
try
{
if (proxy.State != CommunicationState.Closed
&& proxy.State != CommunicationState.Faulted)
{
proxy.Close();
}
else
{
proxy.Abort();
}
}
catch (CommunicationException)
{
proxy.Abort();
}
catch (TimeoutException)
{
proxy.Abort();
}
catch
{
proxy.Abort();
throw;
}
}
This appears to be working as intended. However, when I run Code Analysis in Visual Studio 2010 I still get a CA2000 warning.
CA2000 : Microsoft.Reliability : In
method 'DoSomething()', call
System.IDisposable.Dispose on object
'client' before all references to it
are out of scope.
Is there something I can do to my code to get rid of the warning or should I use SuppressMessage to hide this warning once I am comfortable that I am doing everything possible to be sure the client is disposed of?
Related resources that I've found:
http://www.theroks.com/2011/03/04/wcf-dispose-problem-with-using-statement/
http://www.codeproject.com/Articles/151755/Correct-WCF-Client-Proxy-Closing.aspx
http://codeguru.earthweb.com/csharp/.net/net_general/tipstricks/article.php/c15941/
You could add a call to Dispose in your finally block, after the call to CloseProxy. At that point you can be reasonably sure that Dispose won't throw, although it seems a bit silly to add superfluous code just to keep code analysis happy - I'd probably just suppress the message.
(Whichever option you choose, include very clear comments explaining why the code does what it does.)

try/catch + using, right syntax

Which one:
using (var myObject = new MyClass())
{
try
{
// something here...
}
catch(Exception ex)
{
// Handle exception
}
}
OR
try
{
using (var myObject = new MyClass())
{
// something here...
}
}
catch(Exception ex)
{
// Handle exception
}
I prefer the second one. May as well trap errors relating to the creation of the object as well.
Since a using block is just a syntax simplification of a try/finally (MSDN), personally I'd go with the following, though I doubt it's significantly different than your second option:
MyClass myObject = null;
try
{
myObject = new MyClass();
//important stuff
}
catch (Exception ex)
{
//handle exception
}
finally
{
if (myObject is IDisposable)
{
myObject.Dispose();
}
}
It depends. If you are using Windows Communication Foundation (WCF), using(...) { try... } will not work correctly if the proxy in using statement is in exception state, i.e. Disposing this proxy will cause another exception.
Personally, I believe in minimal handling approach, i.e. handle only exception you are aware of at the point of execution. In other word, if you know that the initialization of a variable in using may throw a particular exception, I wrap it with try-catch. Similarly, if within using body something may happen, which is not directly related to the variable in using, then I wrap it with another try for that particular exception. I rarely use Exception in my catches.
But I do like IDisposable and using though so I maybe biased.
If your catch statement needs to access the variable declared in a using statement, then inside is your only option.
If your catch statement needs the object referenced in the using before it is disposed, then inside is your only option.
If your catch statement takes an action of unknown duration, like displaying a message to the user, and you would like to dispose of your resources before that happens, then outside is your best option.
Whenever I have a scenerio similar to this, the try-catch block is usually in a different method further up the call stack from the using. It is not typical for a method to know how to handle exceptions that occur within it like this.
So my general recomendation is outside—way outside.
private void saveButton_Click(object sender, EventArgs args)
{
try
{
SaveFile(myFile); // The using statement will appear somewhere in here.
}
catch (IOException ex)
{
MessageBox.Show(ex.Message);
}
}
Both are valid syntax. It really comes down to what you want to do: if you want to catch errors relating to creating/disposing the object, use the second. If not, use the first.
There is one important thing which I'll call out here: The first one will not catch any exception arising out of calling the MyClass constructor.
From C# 8.0 on, you can simplify using statements under some conditions to get rid of the nested block, and then it just applies to the enclosing block.
So your two examples can be reduced to:
using var myObject = new MyClass();
try
{
// something here...
}
catch(Exception ex)
{
// Handle exception
}
And:
try
{
using var myObject = new MyClass();
// something here...
}
catch(Exception ex)
{
// Handle exception
}
Both of which are pretty clear; and then that reduces the choice between the two to a matter of what you want the scope of the object to be, where you want to handle instantiation errors, and when you want to dispose of it.
If the object you are initializing in the Using() block might throw any exception then you should go for the second syntax otherwise both the equally valid.
In my scenario, I had to open a file and I was passing filePath in the constructor of the object which I was initializing in the Using() block and it might throw exception if the filePath is wrong/empty. So in this case, second syntax makes sense.
My sample code :-
try
{
using (var obj= new MyClass("fileName.extension"))
{
}
}
catch(Exception ex)
{
//Take actions according to the exception.
}
From C# 8.0, I prefer to use the second one same like this
public class Person : IDisposable
{
public Person()
{
int a = 0;
int b = Id / a;
}
public int Id { get; set; }
public void Dispose()
{
}
}
and then
static void Main(string[] args)
{
try
{
using var person = new Person();
}
catch (Exception ex) when
(ex.TargetSite.DeclaringType.Name == nameof(Person) &&
ex.TargetSite.MemberType == System.Reflection.MemberTypes.Constructor)
{
Debug.Write("Error Constructor Person");
}
catch (Exception ex) when
(ex.TargetSite.DeclaringType.Name == nameof(Person) &&
ex.TargetSite.MemberType != System.Reflection.MemberTypes.Constructor)
{
Debug.Write("Error Person");
}
catch (Exception ex)
{
Debug.Write(ex.Message);
}
finally
{
Debug.Write("finally");
}
}

Prevent Exceptions From WCF Callbacks

I'm making a small chat application. I got to the point where one client sends a message, and then by using callbacks of other clients in the room, they quickly recieve the message. So, if there are 10 people in the room, the service instance of the client who is sending the message, will invoke this in 10 threads:
targetCallback.RecieveMessage(message);
Now, internet connections are volatile, and it could just so happen that it breaks a moment before that's performed, so an exception would be thrown and the client instance automatically destroyed, leaving the message unsent or half-successful.
I found examples that don't really handle those exceptions at all, while other put a simple:
try
{
targetCallback.RecieveMessage(message);
}
catch
{
}
But, is that the best way to handle this exception?
See
http://msdn.microsoft.com/en-us/library/aa354510.aspx
for good advice. Briefly, you should catch TimeoutException and CommunicationException.
I've also seen ObjectDisposedExceptions when calling WCF callbacks, and maybe a SecurityException of some sort, but I can't remember which one.
For applications that need a higher degree of reliability, I write a basic wrapper method that catches all the exceptions and removes that callback from your callback collection. Then I only ever invoke the callback through the wrapper.
Normally I'd also capture some contextual information about the conneciton from the OperationContext like IP address, sessionID and user token so I can identify who failed and log it. But that's left as an exercise to the reader.
public interface ICallbackContract
{
void Operation(string arg);
}
class Program
{
private List<ICallbackContract> Callbacks;
private void SendMessage(string msg)
{
lock (this.Callbacks)
{
foreach (var callback in this.Callbacks)
{
this.InvokeWcf(callback, (c) => c.Operation(msg));
}
}
}
public void InvokeWcf(this ICallbackContract contract, Action<ICallbackContract> op)
{
if (((ICommunicationObject)contract).State != CommunicationState.Opened)
{
lock (this.Callbacks)
Callbacks.Remove(contract);
myLogger.LogError("That contract isn't open! Disconnected.");
return;
}
try
{
op(contract);
}
catch (TimeoutException ex)
{
lock (this.Callbacks)
Callbacks.Remove(contract);
myLogger.LogError("That contract timed out! Disconnected.", ex);
return;
}
catch (CommunicationException ex)
{
...
}
catch (ObjectDisposedException ex)
{
...
}
catch (Exception ex)
}
// Unexpected case.
lock (this.Callbacks)
Callbacks.Remove(contract);
myLogger.FatalError("Something really bad happened!.", ex);
throw;
{
}
}

Categories

Resources