Properly handling HttpClient exceptions within async / await - c#

I was hoping somebody could enlighten me a little bit on an issue I am facing in regards to async/await exception handling with HttpClient. I have written some code to illustrate, and it is being excecuted on both a Windows Phone 8 device and the emulator:
private async void SearchButton_Click(object sender, EventArgs e)
{
try
{
HttpClient client = new HttpClient();
System.Diagnostics.Debug.WriteLine("BEGIN FAULTY REQUEST:");
string response = await client.GetStringAsync("http://www.ajshdgasjhdgajdhgasjhdgasjdhgasjdhgas.tk/");
System.Diagnostics.Debug.WriteLine("SUCCESS:");
System.Diagnostics.Debug.WriteLine(response);
}
catch (Exception exception)
{
System.Diagnostics.Debug.WriteLine("CAUGHT EXCEPTION:");
System.Diagnostics.Debug.WriteLine(exception);
}
}
Tapping the button that invokes this function, produces the following output in the debugger console, the most interesting being the ones in bold:
BEGIN FAULTY REQUEST:
An exception of type 'System.Net.WebException' occurred in System.Windows.ni.dll and wasn't handled before a managed/native boundary
An exception of type 'System.Net.WebException' occurred in System.Windows.ni.dll and wasn't handled before a managed/native boundary
A first chance exception of type 'System.Net.Http.HttpRequestException' occurred in mscorlib.ni.dll
An exception of type 'System.Net.Http.HttpRequestException' occurred in mscorlib.ni.dll and wasn't handled before a managed/native boundary
CAUGHT EXCEPTION:
(and here it prints out the HttpRequestException)
Of course I am expecting an error in this case since the URL I am calling is nonsense. What I am not understanding here, is why the debugger reports that the exceptions are not handled, when the output simultaneously reports that the exception is caught. Also, the UI side of the app becomes much less responsive while the output is being printed, indicating that something is probably amiss.
Is this not the way to handle exceptions when working with async and await? I appreciate any input! Thanks.

As you are using HttpClient, try to use response.EnsureSuccessStatusCode();
Now HttpClient will throw exception when response status is not a success code.
try
{
HttpResponseMessage response = await client.GetAsync("http://www.ajshdgasjhdgajdhgasjhdgasjdhgasjdhgas.tk/");
response.EnsureSuccessStatusCode(); // Throw if not a success code.
// ...
}
catch (HttpRequestException e)
{
// Handle exception.
}
ORIGINAL SOURCE OF THE CODE: http://www.asp.net/web-api/overview/advanced/calling-a-web-api-from-a-net-client

This is an artifact of the debugger. It's determining that an exception is "uncaught" because it's not caught yet. In this case this is expected behavior.
You are handling the exceptions correctly.

The debugger is telling you that this exception is first chance. When a debugger is attached to your process it gets notified for every exception that is thrown and then based on how the debugger has been configured it will decide what to do with it. You can go through What is first chance exception? for more details.
On a side note, catch specific exceptions only so that you understand which exceptions you are expecting and why.

Related

A proper way to handle WCF network related exceptions

In the application I"m working with, there is some communication with the remote service using WCF (basic http binding, no fancy stuff). Since the client is lightweigh, the details of the server are irrelevant, you may assume that there is just a method that always return true (like ping or something).
The proxy is generated using a Task option, the new client instance is created each time the operation is called. Something like this could be spinning inside the timer:
void Foo()
{
var client = new PingServiceClient();
try
{
bool result = client.PingAsync().GetAwaiter().GetResult();
}
catch
{
//log something
}
finally
{
client.Abort();
}
}
My question is, how should I correctly handle the cases when the network is down? Because the behavior is different. I either get an application crashing (I assume on a task finalizer, which is for some reason not handled neither in AppDomain.CurrentDomain.UnhandledException nor in TaskScheduler.UnobservedTaskException), or sometimes it just silently outputs tons of error messages, but not crashing anything. Messages like these:
Exception thrown: 'System.Net.Sockets.SocketException' in System.dll
Exception thrown: 'System.Net.Sockets.SocketException' in System.dll
Exception thrown: 'System.Net.Sockets.SocketException' in System.dll
Exception thrown: 'System.Net.WebException' in System.dll
Exception thrown: 'System.ServiceModel.EndpointNotFoundException' in System.ServiceModel.dll
Exception thrown: 'System.ServiceModel.EndpointNotFoundException' in System.ServiceModel.Internals.dll
Exception thrown: 'System.ServiceModel.EndpointNotFoundException' in System.ServiceModel.Internals.dll
Exception thrown: 'System.ServiceModel.EndpointNotFoundException' in System.ServiceModel.Internals.dll
Exception thrown: 'System.ServiceModel.EndpointNotFoundException' in System.ServiceModel.Internals.dll
Exception thrown: 'System.Net.Sockets.SocketException' in System.dll
Exception thrown: 'System.AggregateException' in mscorlib.dll
I'm struggling to find a graceful way of handling these, so if anybody has some knowledge regarding this please share the approach.
Thanks in advance.
UPD:
I have tried to re-create the proxy with Begin/End pair and override the end method implementation in a partial class:
public partial class PingServiceClient : IPingServiceClient, PingService
{
public Task<bool> PingSync()
{
return Task.Factory.FromAsync(BeginPing(null, null), HandledEndPing);
}
private bool HandledEndPing(System.IAsyncResult result)
{
var res = false;
try
{
res = EndPing(result);
}
catch (Exception e)
{
;
}
return res;
}
}
Still the same barrage of messages in the output as before (the catch is working, though).

Visual Studio - suppress certain "Exception thrown" messages

Can you hide "Exception thrown" messages in output for certain methods (certain code areas)?
I use HttpWebRequest for server communication. I periodically check if the server is available (a few times every second). When a server is not reachable HttpWebRequest throws an exception. I catch it and set GUI elements enabled to false. The problem is when the server is unreachable, output window gets cluttered up with "Exception thrown" messages.
I know you can right-click output window and uncheck "Exception Messages". But I am not only one working on the project and there might be someone who wants to see some other exception messages (in their part of the project).
Example of what I need:
// Keep showing "Exception thrown" message in this method.
static void Foo()
{
try
{
throw new NotImplementedException();
}
catch (NotImplementedException ex)
{
// Process exception
}
}
// Suppress "Exception thrown" message when it is thown in this method.
static void FooSuppress()
{
try
{
throw new ArgumentException();
}
catch (ArgumentException ex)
{
// Process exception
}
}
static void Main(string[] args)
{
Foo();
FooSuppress();
}
Current output:
Exception thrown: 'System.NotImplementedException' in ExceptionTest.dll
Exception thrown: 'System.ArgumentException' in ExceptionTest.dll
Desired output:
Exception thrown: 'System.NotImplementedException' in ExceptionTest.dll
Edit:
Enabling Just my code in Tools/Options/Debugging might help.
We used Npgsql to access PostgreSQL database and some calls had timeout. Everytime call timeouted "Exception thrown" was written to output window (and there were a lot). Just my code prevents that.
To disable the Exception messages:
(1)Like your previous reply, you could disable it in the Output windows.
(2)You could also disable it under TOOLS->Options->Debugging->Output Window.
(3)Or you could just throw the Exception using the Exception Settings under Debug menu->Windows->Exception Settings.
I don't find other workaround to disable it unless you really resolve/handle the Exceptions in your code. I test it using the VS2015 version.
No other good suggestion, but I help you submit a feature here: https://visualstudio.uservoice.com/forums/121579-visual-studio-ide/suggestions/16752127-visual-studio-suppress-certain-exception-thrown-me
You could vote it.
If you are willing to wait a little bit or use a pre-release version, the next version of Visual Studio (VS 15) will have a feature "Add Conditions to Exception Settings"
Add Conditions to Exception Settings When you configure the
debugger to break on thrown exceptions, you can add conditions so that
the debugger will only break when exceptions are thrown in specified
modules.
This will allow you to set filters on when exceptions should break.

How can I make VS break on exceptions in an async Task, without breaking on all exceptions?

As indicated here and here, exceptions occuring in an async Task are technically not unhandled.
This is particularly nasty when working with MVC. It actually took us a while to figure out why it was occurring more and more that exceptions weren't being caught, we had been gradually introducing Web API calls to our aplication the past few weeks.
public async Task<ActionResult> Foo()
{
// ...
}
The suggested workaround is to make VS break on all exceptions instead of only unhandled exceptions. It works, with the annoying 'side-effect' that it does indeed break on all exceptions :)
Is there another workaround that doesn't involve breaking on all exceptions? It can be specific to MVC but doesn't have to be (meaning if it's a general solution that happens to work for MVC).
A) Wrap your calls and throw a custom Exception in your Task code. Break on only throw of your custom exception. You can select the Exceptions for first throw.
B). Debug.Assert() your Task Results, if you have any wait code. i.e., not just firing and forgetting. Tasks return the Exceptions in a property if you wait on them somewhere or stick error handling in a continuation.
psuedo code
i.e. task. continuewith(r => if(!r.Exception is null) Debug.Break()))
etc.
Hope that helps you on the right path.
You could try and listen for this event if nothing else works here
AppDomain.CurrentDomain.UnhandledException
or
AppDomain.CurrentDomain.FirstChanceException
Then you need to put some if-constructs (check what sender for example) to hit your breakpoint only when it makes sense.
The try-catch reference in MSDN has some guidance and examples on exceptions in async methods, and states: "The completed task to which await is applied might be in a faulted state because of an unhandled exception in the method that returns the task. Awaiting the task throws an exception."
For the example given on that page, it states: "The following example illustrates exception handling for async methods. To catch an exception that an async task throws, place the await expression in a try block, and catch the exception in a catch block. Uncomment the throw new Exception line in the example to demonstrate exception handling. The task's IsFaulted property is set to True, the task's Exception.InnerException property is set to the exception, and the exception is caught in the catch block."
Here's the copy from the example given there:
public async Task DoSomethingAsync()
{
Task<string> theTask = DelayAsync();
try
{
string result = await theTask;
Debug.WriteLine("Result: " + result);
}
catch (Exception ex)
{
Debug.WriteLine("Exception Message: " + ex.Message);
}
Debug.WriteLine("Task IsCanceled: " + theTask.IsCanceled);
Debug.WriteLine("Task IsFaulted: " + theTask.IsFaulted);
if (theTask.Exception != null)
{
Debug.WriteLine("Task Exception Message: "
+ theTask.Exception.Message);
Debug.WriteLine("Task Inner Exception Message: "
+ theTask.Exception.InnerException.Message);
}
}
private async Task<string> DelayAsync()
{
await Task.Delay(100);
// Uncomment each of the following lines to
// demonstrate exception handling.
//throw new OperationCanceledException("canceled");
//throw new Exception("Something happened.");
return "Done";
}
// Output when no exception is thrown in the awaited method:
// Result: Done
// Task IsCanceled: False
// Task IsFaulted: False
// Output when an Exception is thrown in the awaited method:
// Exception Message: Something happened.
// Task IsCanceled: False
// Task IsFaulted: True
// Task Exception Message: One or more errors occurred.
// Task Inner Exception Message: Something happened.
// Output when a OperationCanceledException or TaskCanceledException
// is thrown in the awaited method:
// Exception Message: canceled
// Task IsCanceled: True
// Task IsFaulted: False
Enabling "Just My Code" is one way to do this, as suggested here. True, the exceptions are technically not unhandled, but they are unhandled by user code, which gets VS to do the useful thing and show you where the exception occurred.
See this answer for some screenshots.
Obviously this setting has other implications (e.g. you can no longer step through framework code), so this may or may not be suitable.
You could add a handler for TaskScheduler.UnobservedTaskException.
However, perhaps you've already tried that and you want a way to make the debugger break at the original exception rather than in the unobserved task exception handler.

How to print the exception in Windows Phone?

I am trying to code an app for windows phone 8. I want to print the exception to the screen if I get any. So here is what I am doing:
try
{
//The code which I want to handle for exception
}
catch (Exception e)
{
ErrorStatus.Text = e.Message + "\n\n" + e.Source + "\n\n" + e.StackTrace;
}
where ErrorStatus is my TextBlock.
However, the only line in my catch block is giving me an exception during the runtime. The exception is:
A first chance exception of type 'System.UnauthorizedAccessException' occurred in System.Windows.ni.dll
An exception of type 'System.UnauthorizedAccessException' occurred in System.Windows.ni.dll and wasn't handled before a managed/native boundary
Am I doing something wrong syntactically? I am new to C# programming as well as Windows Phone programming.
Edit:
More details of the exception:
System.UnauthorizedAccessException was unhandled by user code
HResult=-2147024891
Message=Invalid cross-thread access.
Source=System.Windows
InnerException:
You need to show your message from the UI thread: web calls always callback on a background worker thread. So, you need to call the Dispatcher to get this to run on the UI thread.
Also you can just use Exception.ToString() to show the message content as a string. This has the advantage of also showing any nested exceptions inside the one you're handling.
As a temporary measure try:
catch (Exception e)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
ErrorStatus.Text = e.ToString();
}
}
More permanently you should either fix the issue or log it to a file so you aren't catching exceptions which are masking bugs in your code.
This is the best way to print out your exception message so that you may know where the problem is:
try{}
catch(Exception ex)
{
await new MessageDialog("Error message:\n\n" + ex.message).ShowAsync();
}

Will an exception get passed back to the calling method?

Let's say in one method I have
try {
callme();
}
catch
{
// handle callme exception
}
Now let's say callme() calls method1() which in turn calls method2() --
If method2() throws an exception should it get thrown back to method1()'s frame, which will then stop any further execution inside of itself and pass the exception thrown from method2() to callme()'s frame and back to the original stackframe?
Will the same occur if I am stepping through code? Or will VS2008 stop as soon as it sees an exception if it is not handled in the originating method?
I am throwing an Exception but then the debugger complains of:
Description: An unhandled exception
occurred during the execution of the
current web request. Please review the
stack trace for more information about
the error and where it originated in
the code.
as soon as i hit the closing bracket of method2().
I'm a bit confused, I thought exceptions were supposed to be passed back all the way up.
At runtime, the exception will bubble up the call stack until one of the following happens:
It is caught in a Catch block
It is caught by a global exception handler
It is not caught by user code and a general exception message is displayed
When debugging the situation is a bit different because the debugger can be set to break on unhandled user exceptions. This could be what's happening in your case. Check the Visual Studio option Debug / Exceptions to see if your debugger is set to catch any unhandled exception before it bubbles up and out of user code.

Categories