When I await
on a method that throws an exception, try/catch do not save application from crashing.
There is a throwing method
void CurrentStep.Process(CancellationToken cancellationToken)
{
throw new Exception();
}
It is called from the UI thread by the means of ICommand.Execute()
ProcessCurrentStepCommand = AsyncCommandFactory.Create(async cancellationToken =>
{
try
{
await Task.Run(() => CurrentStep.Process(cancellationToken));
}
catch {}
CurrentStep = CurrentStep.NextStepViewModel;
});
ProcessCurrentStepCommand
is bound to the button on UI. When I click the button, my application breaks.
I feel that there is a general problem with throwing an exception on UI thread, but at the same time I don't understand why catch block isn't saving me from exception.
I have found the only way that works for me now:
await Task.Factory.StartNew(
action: () => CurrentStep.Process(cancellationToken),
creationOptions: TaskCreationOptions.LongRunning);
But it looks ugly. If I forget in the future what I wanted to do with this code I might think that I need to clean it and get into trouble with some exception knocking out the whole application.
When in debug mode, everything behaves nicely.
Call stack:
UI.exe!UI.Steps.ViewModels.SvmConnectionViewModel.Process(System.Threading.CancellationToken cancellationToken)
UI.exe!UI.MainViewModel..ctor.AnonymousMethod__1() Line 18 mscorlib.dll!System.Threading.Tasks.Task.InnerInvoke() Line 2911 mscorlib.dll!System.Threading.Tasks.Task.Execute() Line 2523 mscorlib.dll!System.Threading.Tasks.Task.ExecutionContextCallback(object obj) Line 2888 mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 581
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 531
mscorlib.dll!System.Threading.Tasks.Task.ExecuteWithThreadLocal(ref System.Threading.Tasks.Task currentTaskSlot) Line 2853 mscorlib.dll!System.Threading.Tasks.Task.ExecuteEntry(bool bPreventDoubleExecution) Line 2792 mscorlib.dll!System.Threading.Tasks.Task.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() Line 2729
mscorlib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch() Line 830 mscorlib.dll!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() Line 1171
- Next break happens in TaskAwaiter.cs in method ThrowForNonSuccess():
NotImplementedException occured: A first chance exception of type 'System.NotImplementedException' occurred in mscorlib.dll
.
Call stack:
mscorlib.dll!System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task task) Line 180
mscorlib.dll!System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task task) Line 170
mscorlib.dll!System.Runtime.CompilerServices.TaskAwaiter.GetResult() Line 125
UI.exe!UI.MainViewModel..ctor(System.Threading.CancellationToken cancellationToken) Line 18
[Resuming Async Method]
mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.InvokeMoveNext(object stateMachine) Line 1065
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 581
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 531
mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.Run() Line 1045
mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.OutputAsyncCausalityEvents>.AnonymousMethod__0() Line 973
mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.ContinuationWrapper.Invoke() Line 1085
mscorlib.dll!System.Runtime.CompilerServices.TaskAwaiter.OutputWaitEtwEvents.AnonymousMethod__0() Line 301
mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.ContinuationWrapper.Invoke() Line 1085
mscorlib.dll!System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation.GetActionLogDelegate.AnonymousMethod__3() Line 470
mscorlib.dll!System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation..cctor.AnonymousMethod__6(object state) Line 393
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) Line 118 Unknown
WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source, System.Delegate method, object args, int numArgs, System.Delegate catchHandler) Line 41 Unknown
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeImpl() Line 583 Unknown
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(object state) Line 528 Unknown
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 581
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 531
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Line 520
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.Invoke() Line 441 Unknown
WindowsBase.dll!System.Windows.Threading.Dispatcher.ProcessQueue() Line 2227 Unknown
WindowsBase.dll!System.Windows.Threading.Dispatcher.WndProcHook(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) Line 2480 Unknown
WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) Line 345 Unknown
WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) Line 494 Unknown WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) Line 111 Unknown WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source, System.Delegate method, object args, int numArgs, System.Delegate catchHandler) Line 41 Unknown
WindowsBase.dll!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs) Line 1447 Unknown WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam) Line 398 Unknown
[Native to Managed Transition]
[Managed to Native Transition]
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) Line 2281 Unknown
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) Line 369 Unknown
WindowsBase.dll!System.Windows.Threading.Dispatcher.Run() Line 328 Unknown
PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) Line 2745
PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) Line 1841 PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) Line 261 PresentationFramework.dll!System.Windows.Application.Run() Line 222 UI.exe!UI.App.Main() [Native to Managed Transition]
mscorlib.dll!System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) Line 2031
Microsoft.VisualStudio.HostingProcess.Utilities.dll!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() Unknown mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) Line 74
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 581
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 531
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Line 520
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() Line 111
[Async Call]
UI.exe!UI.Commands.AsyncCommandFactory.Create(System.Threading.CancellationToken token) Line 27
[Async Call]
UI.exe!UI.NotifyTaskCompletion.WatchTaskAsync(System.Threading.Tasks.Task task) Line 66
[Async Call]
UI.exe!UI.Commands.AsyncCommand.ExecuteAsync(object parameter) Line 55
[Async Call]
UI.exe!UI.Commands.AsyncCommandBase.Execute(object parameter) Line 15
- The next break with the same exception and almost the same as previous stack trace (the difference is only in the first of 4 last methods called).
Call stack:
mscorlib.dll!System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task task) Line 180
mscorlib.dll!System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task task) Line 170
mscorlib.dll!System.Runtime.CompilerServices.TaskAwaiter.GetResult() Line 125
UI.exe!UI.Commands.AsyncCommandFactory.Create(System.Threading.CancellationToken token) Line 27
[Resuming Async Method]
...
- The next one is again differs only in the one method.
Call stack:
mscorlib.dll!System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task task) Line 180
mscorlib.dll!System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task task) Line 170
mscorlib.dll!System.Runtime.CompilerServices.TaskAwaiter.GetResult() Line 125
UI.exe!UI.NotifyTaskCompletion.WatchTaskAsync(System.Threading.Tasks.Task task) Line 66
[Resuming Async Method]
...
- After previous break there are no more raised exceptions and Task.IsFaulted is set to true. Now UI successfully shows the exception message using this binding:
<Label Content="{Binding ProcessCurrentStepCommand.Execution.ErrorMessage}" Visibility="{Binding ProcessCurrentStepCommand.Execution.IsFaulted, Converter={StaticResource BooleanToVisibilityConverter}}" />
Final Edit.
To understand the context of the question and the accepted answer, you will need to look at these articles:
catch
block is catching it. It's just that the debugger is seeing it first and notifying you, that's all. – Stephen Clearythrow new Exception()
right at the begining of your method MyService.DownloadAndCountBytesAsync(), application will also crash when you pressGo
button. – Egor Okhterov