wpf - Exception in async method executing in UI-thread crashes application -
when await
on method throws exception, try/catch not save application crashing.
there throwing method
void currentstep.process(cancellationtoken cancellationtoken) { throw new exception(); }
it called ui thread means of icommand.execute()
processcurrentstepcommand = asynccommandfactory.create(async cancellationtoken => { try { await task.run(() => currentstep.process(cancellationtoken)); } catch {} currentstep = currentstep.nextstepviewmodel; });
processcurrentstepcommand
bound button on ui. when click button, application breaks. feel there general problem throwing exception on ui thread, @ same time don't understand why catch block isn't saving me exception.
i have found way works me now:
await task.factory.startnew( action: () => currentstep.process(cancellationtoken), creationoptions: taskcreationoptions.longrunning);
but looks ugly. if forget in future wanted code might think need clean , trouble exception knocking out whole application.
when in debug mode, 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: 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 managed transition]
[managed 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 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 same exception , same previous stack trace (the difference in 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 1 again differs in 1 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 no more raised exceptions , task.isfaulted set true. ui shows exception message using binding:
<label content="{binding processcurrentstepcommand.execution.errormessage}" visibility="{binding processcurrentstepcommand.execution.isfaulted, converter={staticresource booleantovisibilityconverter}}" />
final edit.
to understand context of question , accepted answer, need @ these articles:
i don’t want propagate exceptions directly main ui loop; want capture exceptions , set properties error handling done via data binding.
in case, need synchronous command starts asynchronous operation, asynchronous operation represented using notifytaskcompletion
(or similar type write). breaking apart operation (into synchronous "start" , asynchronous data binding) easier trying in 1 (which possible - it's code isn't short or reusable):
// represents execution of current step. notifytaskcompletion processcurrentstepcommandexecution { { return _processcurrentstepcommandexecution; } set { _processcurrentstepcommandexecution = value; propertychanged(); } } ... var cancellationtoken = ...; // wherever from. processcurrentstepcommand = new delegatecommand(() => { processcurrentstepcommandexecution = new notifytaskcompletion(async () => { await task.run(() => currentstep.process(cancellationtoken)); // i'm assuming here want move next step if there no errors. // otherwise, should in block. currentstep = currentstep.nextstepviewmodel; }); });
edit:
i believe may running bug in example code article (there used updated code in comments before msdnmag decided delete them all, , i'm working code sample updated, surprisingly long process). bug occurs if task completes synchronously (with exception or success); in case, notifytaskcompletion<t>.taskcompleted
null
.
to fix this, change constructor notifytaskcompletion<t>
this:
{ task = task; if (!task.iscompleted) taskcompletion = watchtaskasync(task); }
to this:
{ task = task; taskcompletion = watchtaskasync(task); }
Comments
Post a Comment