I am firing off a Task of on a background thread pool thread via the following method
private async Task LoadCoreMatchDataAsync()
{
string errorMessage = String.Empty;
...
try
{
if (!HasConnection)
return;
IProgress<string> progressIndicator = new Progress<string>(LoadProgress);
EventsCollection = new BindableCollection<Taurus.MatchDetails>(
await MatchDataService.GetCollectionAsync(
this.client, progressIndicator, this.token));
...
}
catch (TimeoutException toe)
{
errorMessage = String.Format(
"Retrieval of the MatchDetails using connection " +
"\"{0}\" failed with the following TimeoutException: \"{1}\".",
this.ConnectionString,
toe.Message);
}
catch (OperationCanceledException)
{
// Do nothing, cancel silently.
}
// Display any errors.
if (!String.IsNullOrEmpty(errorMessage))
{
await dialogManager.ShowDialog<MessageDialogResult>(
new MessageBoxViewModel("Connection Timeout", errorMessage, mbs));
HasConnection = false;
}
}
where the GetCollectionAsync(...) method is
public async Task<BindableCollection<Taurus.MatchDetails>> GetCollectionAsync(
MongoClient client, IProgress<string> progressIndicator, CancellationToken token)
{
return await Task.Factory.StartNew<BindableCollection<Taurus.MatchDetails>>(() =>
{
... // Somewhere in here we get a TimeoutException thrown.
}, token);
}
the problem is that when in my call to await MatchDataService.GetCollectionAsync(...) I get an expected TimeoutException, VS2012 throws "a TimeoutException was unhandled by user code" message, when clearly I am handling the exception in the "continuation" in the correct way. If I continue rather than break, the exception is indeed caught and I get my expected error message. I am just not sure why VS2012 is telling me that the exception is unahandled?
I am essentially doing what is described clearly in on of Jon Skeets answers here https://stackoverflow.com/a/19865613/626442.
Thanks for your time.
You have "Just My Code" turned on (which I mentioned in my answer in the other question you reference). The debugger is indicating that "User code" (Your code) did not handle the exception--which is true. The exception is caught by the framework code and placed into a Task.
Turn off the "Just My Code" debugger setting (in my opinion, it is a feature that only causes confusion and has very limited usefulness).
Related
Before I use Nito.MVVM, I used plain async/await and it was throwing me an aggregate exception and I could read into it and know what I have. But since Nito, my exceptions are ignored and the program jumps from async code block and continue executes. I know that it catch exceptions because when I put a breakpoint on catch(Exception ex) line it breaks here but with ex = null. I know that NotifyTask has properties to check if an exception was thrown but where I put it, it checks when Task is uncompleted, not when I need it.
View model:
public FileExplorerPageViewModel(INavigationService navigationService)
{
_navigationService = navigationService;
_manager = new FileExplorerManager();
Files = NotifyTask.Create(GetFilesAsync("UniorDev", "GitRemote/GitRemote"));
}
Private method:
private async Task<ObservableCollection<FileExplorerModel>> GetFilesAsync(string login, string reposName)
{
return new ObservableCollection<FileExplorerModel>(await _manager.GetFilesAsync(login, reposName));
}
Manager method(where exception throws):
public async Task<List<FileExplorerModel>> GetFilesAsync(string login, string reposName)
{
//try
//{
var gitHubFiles = await GetGitHubFilesAsync(login, reposName);
var gitRemoteFiles = new List<FileExplorerModel>();
foreach ( var file in gitHubFiles )
{
if ( file.Type == ContentType.Symlink || file.Type == ContentType.Submodule ) continue;
var model = new FileExplorerModel
{
Name = file.Name,
FileType = file.Type.ToString()
};
if ( model.IsFolder )
{
var nextFiles = await GetGitHubFilesAsync(login, reposName);
var count = nextFiles.Count;
}
model.FileSize = file.Size.ToString();
gitRemoteFiles.Add(model);
}
return gitRemoteFiles;
//}
//catch ( WebException ex )
//{
// throw new Exception("Something wrong with internet connection, try to On Internet " + ex.Message);
//}
//catch ( Exception ex )
//{
// throw new Exception("Getting ExplorerFiles from github failed! " + ex.Message);
//}
}
With try/catch or without it has the same effect. This behavior is anywhere where I have NotifyTask.
Update
There is no event, that fires when exception occurred, but there is Property Changed event, so I used it and added this code:
private void FilesOnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
throw new Exception("EXCEPTION");
bool failed;
if ( Files.IsFaulted )
failed = true;
}
And exception not fires.
I added throw exception in App class (main class) and it fired. And when I have exceptions that come from XAML, it also fires. So maybe it not fires when it comes from a view model, or something else. I have no idea. Will be very happy for some help with it.
Update
We deal with exception = null, but the question is still alive. What I wanna add, that I rarely this issue, when the app is starting to launch on the physic device. I read some info about it, and it doesn't seem to be related, but maybe it is:
I'm not entirely sure what your desired behavior is, but here's some information I hope you find useful.
NotifyTask is a data-bindable wrapper around Task. That's really all it does. So, if its Task faults with an exception, then it will update its own data-bindable properties regarding that exception. NotifyTask is intended for use when you want the UI to respond to a task completing, e.g., show a spinner while the task is in progress, an error message if the task faults, and data if the task completes successfully.
If you want your application to respond to the task faulting (with code, not just a UI update), then you should use try/catch like you have commented out in GetFilesAsync. NotifyTask doesn't change how those exceptions work; they should work just fine.
I know that it catch exceptions because when I put a breakpoint on catch(Exception ex) line it breaks here but with ex = null.
That's not possible. I suggest you try it again.
I know that NotifyTask has properties to check if an exception was thrown but where I put it, it checks when Task is uncompleted, not when I need it.
If you really want to (asynchronously) wait for the task to complete and then check for exceptions, then you can do so like this:
await Files.TaskCompleted;
var ex = Files.InnerException;
Or, if you just want to re-raise the exception:
await Files.Task;
Though I must say this usage is extremely unusual. The much more proper thing to do is to have a try/catch within your GetFilesAsync.
I have code that catches all exceptions that are thrown by a server call as follows:
new public Task SaveAsync()
{
return ServerException.Wrap(base.SaveAsync);
}
Where ServerException.Wrap looks like:
public static async Task<T> Wrap<T>(Func<Task<T>> func)
{
try
{
return await func();
}
catch (Exception ex)
{
// This is an internal error that shouldn't happen.
throw new ServerException(ex);
}
}
public static async Task Wrap(Func<Task> func)
{
await Wrap(async () =>
{
await func();
return true;
});
}
And then I have a function that calls SaveAsync as follows:
try
{
await problem.SaveAsync();
}
catch (ServerException ex)
{
Logger.LogException("Error saving problem.", ex);
}
I have some internal error that generates an exception which I catch in the above line and then it gets logged as follows:
2015-10-20 11:20:44.502 [Line 99] Error saving problem. (Exception:
Exceptions.ServerException: ---> System.ArgumentException: An item
with the same key has already been added. at
System.ThrowHelper.ThrowArgumentException (ExceptionResource resource)
[0x00000] in
/Users/builder/data/lanes/1977/2c66d2fe/source/mono/external/referencesource/mscorlib/system/throwhelper.cs:74
However a few seconds later I get an unhanded exception warning that gets logged:
2015-10-20 11:21:16.352 Warning: Unhandled exception:
System.AggregateException: A Task's exception(s) were not observed
either by Waiting on the Task or accessing its Exception property. As
a result, the unobserved exception was rethrown by the finalizer
thread. ---> System.ArgumentException: An item with the same key has
already been added. at System.ThrowHelper.ThrowArgumentException
(ExceptionResource resource) [0x00000] in
/Users/builder/data/lanes/1977/2c66d2fe/source/mono/external/referencesource/mscorlib/system/throwhelper.cs:74
Why do I get the second unobserved exception, even though I am catching and handling the first exception? This exception seems to be thrown by my ServerException.Wrap method.
I am using MonoTouch.
You need to explicitly set the exception to observed.
For that, you need to subscribe to the TaskScheduler's UnobservedTaskException event, and set it explicitly to observed (call SetObserved() on it).
See here:
UnobservedTaskException being throw...
EDIT:
Of course, you can also just catch AggregateException as well, or use ContinueWith() to observe and resume the task.
See the bottom of the official documentation:
Exception Handling (MSDN)
I'm developing an application in C# that communicates with Dynamics NAV through web services. To reduce duplicate code and because there will be many endpoints, I have created a generic async/await method that executes the service calls and handle exceptions.
The method works but I'm seeing an unexpected behavior in the Visual Studio 2013 output window when an exception occur(and is handled).
Test code and output can be seen below.
My concern is the "A first chance exception of type..." lines which I'm seeing 4 times when using the async/await methods. Does this exception really occur 4 times?
When calling the service synchronously there's only one exception line which is expected.
Is this just Visual Studio 2013 or is there something wrong with my async/await code?
Is there maybe a better way of doing what I'm trying to accomplish?
class Program
{
static void Main(string[] args)
{
Debug.WriteLine("Synchronous...");
try
{
TestFunctions_PortClient service = new TestFunctions_PortClient();
service.Open();
string result = service.ErrorTest();
Debug.WriteLine(result);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
Debug.WriteLine(string.Empty);
Debug.WriteLine("Async...");
NavServiceTest navService = new NavServiceTest();
navService.TestAsync();
Console.ReadLine();
}
}
class NavServiceTest
{
public async void TestAsync()
{
try
{
string result = await CallServiceAsync();
Debug.WriteLine(result);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
private async Task<string> CallServiceAsync()
{
TestFunctions_PortClient service = new TestFunctions_PortClient();
service.Open();
ErrorTest_Result result = await ExecuteServiceAsync<ErrorTest_Result>(
service.InnerChannel,
service.Endpoint,
service.ErrorTestAsync());
return result.return_value;
}
private async Task<T> ExecuteServiceAsync<T>(IClientChannel channel, ServiceEndpoint endpoint, Task<T> source)
{
var tcs = new TaskCompletionSource<T>();
Task<T> task = tcs.Task;
try
{
Debug.WriteLine("ExecuteServiceAsync");
tcs.TrySetResult(await source);
}
catch (EndpointNotFoundException ex)
{
Debug.WriteLine("EndpointNotFoundException");
tcs.TrySetException(ex);
}
catch (FaultException ex)
{
Debug.WriteLine("FaultException");
tcs.TrySetException(ex);
}
catch (Exception ex)
{
Debug.WriteLine("Exception");
tcs.TrySetException(ex);
}
finally
{
if (channel != null)
{
if (channel.State == CommunicationState.Faulted)
channel.Abort();
else
channel.Close();
}
}
if (task.IsFaulted)
{
throw task.Exception.InnerException;
}
return task.Result;
}
}
Here's the output of the code above.
Synchronous...
A first chance exception of type 'System.ServiceModel.FaultException' occurred in mscorlib.dll
Error from NAV
Async...
ExecuteServiceAsync
A first chance exception of type 'System.ServiceModel.FaultException' occurred in mscorlib.dll
FaultException
A first chance exception of type 'System.ServiceModel.FaultException' occurred in ServiceTest.exe
A first chance exception of type 'System.ServiceModel.FaultException' occurred in mscorlib.dll
A first chance exception of type 'System.ServiceModel.FaultException' occurred in mscorlib.dll
Error from NAV
When an exception occurs in an async method, it doesn't just propagate up the stack like it does in synchronous code. Heck, the logical stack is likely not to be there any more.
Instead, the exception is stored in the task which represents the asynchronous operation. Then, when you await the asynchronous operation, the GetResult method of the TaskAwaiter will rethrow the original exception. If that isn't caught in your code, then it will be caught by the compiler-generated code again and put into the task that represents that operation, etc. So if you have a chain of asynchronous methods (as is often the case) and the deepest one throws an exception, the exception propagation will actually be a "throw in GetResult, catch, stuff into task" per link in the chain.
So yes, the exception is being thrown four times, in order to effectively only be thrown once. If you're worried about the efficiency of that, I suspect it's not too bad - because the logical stack trace is only determined once. I dare say it's less efficient than the synchronous version, but my general philosophy is that if you're seeing so many exceptions that they're affecting your performance significantly, then either you're overusing exceptions or your system is in a really bad state anyway, and performance is the least of your worries.
Given the following simplified code
/// <summary>
/// Within the VS2010 debugger, the following test will cease with an
/// "Exception was unhandled by user code".
/// (Debug window reports a "A first chance exception of type
/// 'System.Exception' ..." BEFORE the exception is caught
/// further down in the execution path.)
/// OUTSIDE the VS2010 debugger, the exception is caught by the tComplete
/// task that follows the tOpen task, just as expected.
/// </summary>
public void StartToOpen_Simple()
{
Task tOpen = Task.Factory.StartNew(() => {
//do some work before spawning another task here
try
{
return Task.Factory.StartNew(() => {
Thread.Sleep(2000);
//First chance exception occurs here:
throw new Exception("Some generic exception");
}, TaskCreationOptions.AttachedToParent);
} catch (Exception ex)
{
//never fires
var source = new TaskCompletionSource<object>();
source.TrySetException(ex);
return source.Task;
}
}).Unwrap();
Task tComplete = tOpen.ContinueWith(t => {
if (t.Exception != null)
{
Exception LastOpenException = t.Exception.Flatten().GetBaseException();
if (LastOpenException is OperationCanceledException)
{
Console.WriteLine("OperationCanceledEx: " + LastOpenException.Message);
} else
{
Console.WriteLine("Some exception occured in the tOpen task, but we're prepared for it here in the tComplete task.");
Console.WriteLine("The exception message was: {0}", LastOpenException.Message);
}
} else
{
//do something if no exception occured (doesn't happen in this example)
}
}, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.AttachedToParent, TaskScheduler.Default);
}
and testing it for example via
static void Main(string[] args)
{
AsyncTest test = new AsyncTest();
test.StartToOpen_Simple();
Console.WriteLine("Started async task. Waiting for exception");
Console.ReadKey();
}
I observe a very annoying issue while running it in the VS2010 debugger: Just like the "Summary" states, the debugger breaks at the throw in the 'tOpen' task believing that I didn't catch the exception (which i do "further below" in the 'tComplete' task). Only if I continue the debugging session do I see that the exception is "bubbled up" and hence handled as desired. If this method were run on a regular time interval (which it is!) debugging this becomes a nightmare, because the debugger breaks on each interval.
Running the program on a console, doesn't exhibit this behavior.
Can someone explain to me why the Debugger breaks at this line, i.e. it doesn't see
What are my options of being able to reasonably debug code inside VS2010 where such code exists?
First chance exception messages most often do not mean there is a problem in the code. For applications / components which handle exceptions gracefully, first chance exception messages let the developer know that an exceptional situation was encountered and was handled.
Please refer this
Typically, for code that I don't expect to throw exceptions but does (i.e. a programming error), I want my application to crash (so that it doesn't corrupt data, report invalid data to the user, etc.).
Is there a best practice for getting (closer to) this behavior when using Tasks? We've registered a handler for TaskScheduler.UnobservedTaskException. The problem is that this can occur much later than the causing unexpected exception.
Question:
Which option should I use if any:
Should I wrap my Tasks action in a try/catch and escalate in the catch for exceptions I don't expect? And if so, what should I do to escalate (i.e. I'd like to get it to fire the AppDomain.UnhandledException event and terminate.
Should I attach a continuation (OnlyOnFaulted) on the ui thread (this is a Winforms application) that rethrows the exception if it is not an expected exception?
Is there a better or more standard approach?
Here's what #1 might look like:
var t1 = Task.Factory.StartNew(() =>
{
try
{
string path = null; // Programming error. Should have been a valid string. Will cause System.ArgumentNullException below
using (FileStream fs = File.Create(path))
{
}
}
catch (System.IO.IOException) { throw; } // Expected possible exception
catch (System.UnauthorizedAccessException) { throw; }
catch
{
// Anything caught here is not an expected exception and should be escalated.
// But how?
}
});
Here's what #2 might look like:
TaskScheduler uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
var t1 = Task.Factory.StartNew(() =>
{
string path = null; // Programming error. Should have been a valid string. Will cause System.ArgumentNullException below
using (FileStream fs = File.Create(path))
{
}
});
t1.ContinueWith(t =>
{
Exception ex = t.Exception;
if (ex is IOException || ex is UnauthorizedAccessException) // Expected exceptions (do nothing)
return;
throw ex; // Not expected (escalate by rethrowing)
}, CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, uiTaskScheduler);
Attaching a continuation feels like a good approach to me. If you're comfortable with the assumption that you won't be blocking the UI thread for too long for other reasons, forcing the continuation to run on the UI thread seems like a very reasonable option to me. That way you can perform any UI tasks you need to as well, as part of the emergency shutdown.