How can I close WCF Service connections when I close my program - c#

I am hosting my WCF service on a windows Azure website. In my program I select between 1-16 users and for each user selected I contact my wcf service and return the data using the format below:
try
{
...
client.Close();
}
catch (CommunicationException e)
{
...
client.Abort();
}
catch (TimeoutException e)
{
...
client.Abort();
}
catch (Exception e)
{
...
client.Abort();
throw;
}
The WCF service is contacting an azure SQL database to get the data which means the service call may last up to 10 seconds in total. But if i close the program while retreiving data and open it again and try to retrieve data the connection times out and I get a HTTP server error on my azure website which is then subsequently down for 2-3 minutes.
How can I close the WCF service connections on closing my program. should I be using a "Using" statment instead? And also should I try refactor my code to only contact the service once rather than once for each user selected?

It will be closed automatically. But if you want to be sure, you can use finally block:
try
{
...
client.Close();
}
finally
{
if(client.State != CommunicationState.Closed)
client.Abort();
}

When you said you close the program, did you close the program through terminating the process in Task Manager? If so, because the program is closed disgracefully, there may not be Tcp/IP conversation for closing the connection.
If you close the program gracefully so client.dispose() will be called, the server will be acknowledged of the closure of the connection, rather than waiting for tcp/ip packet arriving and keeping the connection open.
You may be using try-finally block as Uriil suggested.
or
try
{
using (...)
{
...
}
}
catch (some exceptions...

Related

Handling WCF errors

I have a desktop c# app that uploads a stream of images to my server using WCF.
For testing I wanted to simulate handling errors when my server is down.
When I looked on MSDN it told me to use the Abort method, which I implemented.
This is my code:
try
{
wcf.UploadMotionDynamicRaw(package);
}
catch (TimeoutException tex)
{
wcf.Abort();
//log error
}
catch (ServiceActivationException sae)
{
wcf.Abort();
//log error
}
catch (CommunicationException)
{
wcf.Abort();
ErrorLogger.AddError("Engine", "ProcessFrame.3", new Exception("Service Communication Error"));
}
catch (Exception ex)
{
wcf.Abort();
//log error
}
So, to test this I run my client app. I went to my server and stopped IIS. I waited a few seconds and restarted IIS.
The streaming did not resume.
I am guessing that after I used Abort() I would need to reconnect my client?
If so then that would be impractical for my application.
Is there a better way of dealing with server/internet issues in terms of 'tidying up' after an error has been thrown?
Thanks

Prevent console app from closing after catching exception

I've written an IRC bot in C# using SmartIrc4Net, the purpose of the bot is to just provide information when a command is recognised.
My problem is that, exceptions can happen in the code which causes the application to close but is it possible to keep the application running and not have any "press any key to continue" messages to appear. This should ideally just log the exception and continue on.
I know I could manage the exception in the first place but validating all the input on a per command basis will take a long time. Or there might even be other exceptions I might not have covered.
static void Main(string[] args)
{
IrcClient bot = new IrcClient();
// attach events
try
{
// connect to server, login etc
// here we tell the IRC API to go into a receive mode, all events
// will be triggered by _this_ thread (main thread in this case)
// Listen() blocks by default, you can also use ListenOnce() if you
// need that does one IRC operation and then returns, so you need then
// an own loop
bot.Listen();
// disconnect when Listen() returns our IRC session is over
bot.Disconnect();
}
catch (ConnectionException e)
{
Console.WriteLine("Couldn't connect! Reason: " + e.Message);
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(">> Error: " + e);
}
}
Wrap your program in a while(true) block.
static void Main(string[] args)
{
while(true){
IrcClient bot = new IrcClient();
// attach events
try
{
// connect to server, login etc
// here we tell the IRC API to go into a receive mode, all events
// will be triggered by _this_ thread (main thread in this case)
// Listen() blocks by default, you can also use ListenOnce() if you
// need that does one IRC operation and then returns, so you need then
// an own loop
bot.Listen();
// disconnect when Listen() returns our IRC session is over
bot.Disconnect();
}
catch (ConnectionException e)
{
Console.WriteLine("Couldn't connect! Reason: " + e.Message);
}
catch (Exception e)
{
Console.WriteLine(">> Error: " + e);
}
}
}
exceptions can happen in the code which causes the application to
close but is it possible to keep the application running and not have
any "press any key to continue" messages to appear.
Well... yes, you could write your application that way, but I can pretty much guarantee it's not the easy way out you think it is. When an exception is thrown, something has gone wrong. You don't magically fix anything by shrugging your shoulders and carrying on regardless, all that's likely to result from that is that more things will go wrong.
Imagine for a moment you have code that opens a file, and then does something with the contents of that file, and then displays some results to the user. If the file doesn't exist, an exception will be thrown. If you just catch the exception, do nothing, and then carry on with the "do something with the contents of the file" code... congratulations, now you have more exceptions to deal with because there are no contents of the file. You shrug your shoulders again, carry on with the "display the results" code... and congratulations, yet more exceptions because there are no results!
There is no lazy way out. Catch specific exceptions, and handle them appropriately. Yes, this takes more effort. Yes, it takes more code. Yes, you are going to have to think about what "handle it appropriately" means in each individual case. That's programming.
you should try this
static void Main(string[] args)
{
bool shouldStop=false;
while(!shouldStop){
IrcClient bot = new IrcClient();
shouldStop=true;
// attach events
try
{
// connect to server, login etc
// here we tell the IRC API to go into a receive mode, all events
// will be triggered by _this_ thread (main thread in this case)
// Listen() blocks by default, you can also use ListenOnce() if you
// need that does one IRC operation and then returns, so you need then
// an own loop
bot.Listen();
// disconnect when Listen() returns our IRC session is over
bot.Disconnect();
}
catch (ConnectionException e)
{
Console.WriteLine("Couldn't connect! Reason: " + e.Message);
shouldStop=false;
}
catch (Exception e)
{
Console.WriteLine(">> Error: " + e);
shouldStop=false;
}
}
}

Reading data from a server and detecting network unavailability in C#

I have a simple task: to read data from a server, if the server is unreachable (server down or bad network), load data (possibly stale) from local disk cache.
Here's a simple pseudo representation of what the Java code would look like:
try {
//read from server
} catch (IOException ioe) {
//most likely a socket timeout exception
//read from local disk
} finally {
//free I/O resources
}
but implementing that in C# doesn't seem to work as WebClient doesn't seem to throw any exception even when there's no internet access on the host machine so there's no way to detect that condition via the catch block and revert back to the local cache.
I'm aware of WebClient's async APIs and its rather funny callback chain but I perceive this as too awkward and doesn't suit my design goal properly. Is there a way I can do this in C# as easily as the Java skeleton code shown above? Thanks.
WebClient will timeout, but only after 100s.
I would recommend you use HttpWebRequest instead. This has a settable timeout property.
See http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.timeout.aspx
Furthermore to bobbymond's answer, it's a WebException that will be returned by the WebClient, so that's what you're looking to catch:
WebClient wc = new WebClient();
try
{
wc.Credentials = new NetworkCredential("Administrator", "SomePasword", "SomeDomain");
byte[] aspx = wc.DownloadData("http://SomeServer/SomeSub/SomeFile.aspx");
}
catch (WebException we)
{
//Catches any error in the WebClient, including an inability to contact the remote server
}
catch (System.Exception ex)
{
}

3dparty component leaves dead threads

While an app tries to connect to database server and retrieve some data, it sometimes raise an exception and it seems like it leaves dead threads when expcetion raised even when it's handled. So there are about 300 threads that getting service down.
Here is code invoked periodically on timer:
Parallel.ForEach(dbs, pair =>
{
db l = pair.Value;
if (String.IsNullOrEmpty(l.city))
l.city = l.configCity;
using (OracleConnection conn = new OracleConnection(l.connString))
{
try
{
conn.Open();
}
catch (Exception exc)
{
Console.WriteLine(String.Format("({0}, {1}): {2}{3}", l.connAlias, l.lid, exc.Message, Environment.NewLine));
}
try
{
if ((conn != null) && (conn.State == ConnectionState.Open))
{
// This method just call stored procedure and then set received data to 'l' object
if (!DbConnection.SetBadicData(conn, ref l))
{
Console.WriteLine(String.Format("Couldn't refresh basic data on ({0}, {1})", l.connAlias, l.id));
}
// This method also just call procedure and set received data to object
if (!DbConnection.SetExtendedData(conn, ref l))
{
Console.WriteLine(String.Format("Couldn't refresh advanced data on ({0}, {1})", l.connAlias, l.lid));
}
}
}
catch (Exception exc)
{
Console.WriteLine(String.Format("({0}, {1}): {2}{3}", l.connAlias, l.lid, exc.Message, Environment.NewLine));
}
}
});
Exceptions are:
Attempted to read or write protected memory. This is often an
indication that other memory is corrupt
Internal exception in Oracle client
SEHException - External component has thrown an exception
Component that used to connect to database is devArt dotConnect for Oracle.
How can I manage it guys? Does BeginConnect and then forced breaking by EndConnect will help?
Get a fixed library :-)
But seriously. If you have a third party library that you have to use, cannot change it and which is buggy, the only way I see is to run it in a separate AppDomain. Communication between domains is more difficult than just calling a method but still relatively easy. You can for example use a WCF service (with named pipe) to communicate.
Once you have your code handling nasty library in a separate AppDomain, you can recycle (destroy and recreate) that domain periodically or under other conditions. That will kill off all hanging threads, unreleased objects etc.
It is a workaround type of solution but it should give you at least a way out of this.

Exception in "using" statement with WCF not closing connections properly. How does one close faulted WCF client connections or those with exceptions?

There are several questions on StackOverflow regarding closing WCF connections, however the highest ranking answers refers to this blog:
http://marcgravell.blogspot.com/2008/11/dontdontuse-using.html
I have a problem with this technique when I set a breakpoint at the server and let the client hang for more than one minute. (I'm intentionally creating a timeout exception)
The issue is that the client appears to "hang" until the server is done processing. My guess is that everything is being cleaned up post-exception.
In regard to the TimeOutException it appears that the retry() logic of the client will continue to resubmit the query to the server over and over again, where I can see the server-side debugger queue up the requests and then execute each queued request concurrently. My code wan't expecting WCF to act this way and may be the cause of data corruption issues I'm seeing.
Something doesn't totally add up with this solution.
What is the all-encompassing modern way
of dealing with faults and exceptions
in a WCF proxy?
Update
Admittedly, this is a bit of mundane code to write. I currently prefer this linked answer, and don't see any "hacks" in that code that may cause issues down the road.
This is Microsoft's recommended way to handle WCF client calls:
For more detail see: Expected Exceptions
try
{
...
double result = client.Add(value1, value2);
...
client.Close();
}
catch (TimeoutException exception)
{
Console.WriteLine("Got {0}", exception.GetType());
client.Abort();
}
catch (CommunicationException exception)
{
Console.WriteLine("Got {0}", exception.GetType());
client.Abort();
}
Additional information
So many people seem to be asking this question on WCF that Microsoft even created a dedicated sample to demonstrate how to handle exceptions:
c:\WF_WCF_Samples\WCF\Basic\Client\ExpectedExceptions\CS\client
Download the sample:
C# or VB
Considering that there are so many issues involving the using statement, (heated?) Internal discussions and threads on this issue, I'm not going to waste my time trying to become a code cowboy and find a cleaner way. I'll just suck it up, and implement WCF clients this verbose (yet trusted) way for my server applications.
Optional Additional Failures to catch
Many exceptions derive from CommunicationException and I don't think most of those exceptions should be retried. I drudged through each exception on MSDN and found a short list of retry-able exceptions (in addition to TimeOutException above). Do let me know if I missed an exception that should be retried.
Exception mostRecentEx = null;
for(int i=0; i<5; i++) // Attempt a maximum of 5 times
{
try
{
...
double result = client.Add(value1, value2);
...
client.Close();
}
// The following is typically thrown on the client when a channel is terminated due to the server closing the connection.
catch (ChannelTerminatedException cte)
{
mostRecentEx = cte;
secureSecretService.Abort();
// delay (backoff) and retry
Thread.Sleep(1000 * (i + 1));
}
// The following is thrown when a remote endpoint could not be found or reached. The endpoint may not be found or
// reachable because the remote endpoint is down, the remote endpoint is unreachable, or because the remote network is unreachable.
catch (EndpointNotFoundException enfe)
{
mostRecentEx = enfe;
secureSecretService.Abort();
// delay (backoff) and retry
Thread.Sleep(1000 * (i + 1));
}
// The following exception that is thrown when a server is too busy to accept a message.
catch (ServerTooBusyException stbe)
{
mostRecentEx = stbe;
secureSecretService.Abort();
// delay (backoff) and retry
Thread.Sleep(1000 * (i + 1));
}
catch(Exception ex)
{
throw ex; // rethrow any other exception not defined here
}
}
if (mostRecentEx != null)
{
throw new Exception("WCF call failed after 5 retries.", mostRecentEx );
}
Closing and Disposing a WCF Service
As that post alludes to, you Close when there were no exceptions and you Abort when there are errors. Dispose and thus Using shouldn't be used with WCF.

Categories