Pix*_*xar 3 wpf exception ui-thread task-parallel-library async-await
当我await使用抛出异常的方法时,try/catch 不会使应用程序免于崩溃。
有一种投掷方法
void CurrentStep.Process(CancellationToken cancellationToken)
{
throw new Exception();
}
Run Code Online (Sandbox Code Playgroud)
它是通过以下方式从 UI 线程调用的:ICommand.Execute()
ProcessCurrentStepCommand = AsyncCommandFactory.Create(async cancellationToken =>
{
try
{
await Task.Run(() => CurrentStep.Process(cancellationToken));
}
catch {}
CurrentStep = CurrentStep.NextStepViewModel;
});
Run Code Online (Sandbox Code Playgroud)
ProcessCurrentStepCommand绑定到 UI 上的按钮。当我单击按钮时,我的应用程序崩溃了。我觉得在 UI 线程上抛出异常存在一个普遍的问题,但同时我不明白为什么 catch 块不能让我免于异常。
我现在找到了唯一适合我的方法:
await Task.Factory.StartNew(
action: () => CurrentStep.Process(cancellationToken),
creationOptions: TaskCreationOptions.LongRunning);
Run Code Online (Sandbox Code Playgroud)
但看起来很丑。如果我将来忘记了我想用这段代码做什么,我可能会认为我需要清理它,并因某些异常而导致整个应用程序崩溃而陷入麻烦。
当处于调试模式时,一切都表现良好。
调用堆栈:
UI.exe !UI.Steps.ViewModels.SvmConnectionViewModel.Process(System.Threading.CancellationToken CancellationToken)
UI.exe !UI.MainViewModel..ctor.AnonymousMethod__1() 第 18 行 mscorlib.dll !System.Threading.Tasks.Task.InnerInvoke ()第2911行 mscorlib.dll!System.Threading.Tasks.Task.Execute()第2523行 mscorlib.dll!System.Threading.Tasks.Task.ExecutionContextCallback(object obj)第2888行 mscorlib.dll!System.Threading.ExecutionContext。 RunInternal(System.Threading.ExecutionContextexecutionContext,System.Threading.ContextCallback回调,对象状态,布尔保留SyncCtx)第581行
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContextexecutionContext,System.Threading.ContextCallback回调,对象状态,boolserveSyncCtx)第531行
mscorlib.dll!System.Threading.Tasks.Task.ExecuteWithThreadLocal(ref System.Threading.Tasks.Task currentTaskSlot)第2853行 mscorlib.dll!System.Threading.Tasks.Task.ExecuteEntry(bool bPreventDoubleExecution) )第2792行 mscorlib.dll!System.Threading.Tasks.Task.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()第2729行
mscorlib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch()第830行 mscorlib.dll!System.Threading._ThreadPoolWaitCallback .PerformWaitCallback() 第 1171 行
NotImplementedException occured: A first chance exception of type 'System.NotImplementedException' occurred in mscorlib.dll。

调用堆栈:
mscorlib.dll !System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task 任务) 第 180 行
mscorlib.dll !System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task 任务) 第 170 行
mscorlib.dll !System.Runtime.CompilerServices.TaskAwaiter.GetResult() 第 125 行
UI.exe !UI.MainViewModel..ctor(System.Threading.CancellationToken CancelToken) 第 18 行
[恢复异步方法]
mscorlib.dll !System.Runtime. CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.InvokeMoveNext(对象stateMachine)第1065行
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContextexecutionContext,System.Threading.ContextCallback回调,对象状态,布尔保留SyncCtx)第581行
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContextexecutionContext,System.Threading.ContextCallback回调,对象状态,boolpreserveSyncCtx)第531行
mscorlib.dll!System.Runtime.CompilerServices.AsyncMethodBuilderCore.MoveNextRunner.Run()第1045行
mscorlib.dll !System.Runtime.CompilerServices.AsyncMethodBuilderCore.OutputAsyncCausalityEvents>.AnonymousMethod__0() 第 973 行
mscorlib.dll !System.Runtime.CompilerServices.AsyncMethodBuilderCore.ContinuationWrapper.Invoke() 第 1085 行
mscorlib.dll !System.Runtime.CompilerServices.TaskAwaiter .outputwaitetWevents.AnonymousMethod__0()行301
mscorlib.dll!system.runtime.compilerServices.asyncmethodbuildercore.continuationwrrapper.invoke.invoke()行1085
mscorlib.dll!system.thread! 3()行470
mscorlib.dll! System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation..cctor.AnonymousMethod__6(对象状态) 第 393 行
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate 回调,对象 args,int numArgs) 第 118 行 未知
WindowsBase.dll! MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source, System.Delegate method, object args, int numArgs, System.Delegate catchHandler) 第 41 行未知
WindowsBase.dll !System.Windows.Threading.DispatcherOperation.InvokeImpl() 第 583 行未知
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(对象状态)第528行未知
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContextexecutionContext,System.Threading.ContextCallback回调,对象状态,boolpreserveSyncCtx)第581行
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContextexecutionContext, System.Threading.ContextCallback 回调,对象状态,bool keepSyncCtx) 第 531 行
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContextexecutionContext,System.Threading.ContextCallback 回调,对象状态) 第 520 行
WindowsBase.dll! System.Windows.Threading.DispatcherOperation.Invoke() 第 441 行未知
WindowsBase.dll !System.Windows.Threading.Dispatcher.ProcessQueue() 第 2227 行未知
WindowsBase.dll !System.Windows.Threading.Dispatcher.WndProcHook(System.IntPtr hwnd 、 int msg、System.IntPtr wParam、System.IntPtr lParam、ref bool 已处理)第 2480 行未知
WindowsBase.dll !MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd、int msg、System.IntPtr wParam、System.IntPtr lParam ,ref bool 已处理)第 345 行未知
WindowsBase.dll !MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) 第 494 行未知 WindowsBase.dll !System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate 回调,对象 args,int numArgs ) 第 111 行未知 WindowsBase.dll !MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source, System.Delegate method, object args, int numArgs, System.Delegate catchHandler) 第 41 行未知
WindowsBase.dll !System.Windows.Threading。 Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority优先级,System.TimeSpan超时,System.Delegate方法,对象args,int numArgs)第1447行未知 WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd,int) msg、System.IntPtr wParam、System.IntPtr lParam) 第 398 行未知
[本机到托管转换]
[托管到本机转换]
WindowsBase.dll !System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame 框架)第2281行未知的
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame框架)第369行未知的
WindowsBase.dll!System.Windows.Threading.Dispatcher.Run()第328行未知的
PresentationFramework.dll!System.Windows.Application.RunDispatcher(对象忽略)第2745行
PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window窗口)第1841行 PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) 第 261 行 PresentationFramework.dll !System.Windows.Application.Run() 第 222 行 UI.exe!UI.App.Main() [本机到托管转换]
mscorlib.dll !System.AppDomain.ExecuteAssembly(string assemblyFile, System.Security.Policy.Evidence assemblySecurity, string[] args) 第 2031 行
Microsoft.VisualStudio.HostingProcess.Utilities.dll !Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()未知 mscorlib.dll !System.Threading.ThreadHelper.ThreadStart_Context(对象状态) 第 74 行
mscorlib.dll !System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContextexecutionContext、System.Threading.ContextCallback 回调、对象状态、boolserveSyncCtx)第581行
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContextexecutionContext,System.Threading.ContextCallback回调,对象状态,boolpreserveSyncCtx)第531行
mscorlib.dll!System.Threading.ExecutionContext.Run(System。 Threading.ExecutionContextexecutionContext,System.Threading.ContextCallback回调,对象状态)第520行
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart()第111行
[异步调用]
UI.exe!UI.Commands.AsyncCommandFactory.Create(System。 Threading.CancellationToken 令牌)第 27 行
[异步调用]
UI.exe !UI.NotifyTaskCompletion.WatchTaskAsync(System.Threading.Tasks.Task 任务) 第 66 行
[异步调用]
UI.exe !UI.Commands.AsyncCommand.ExecuteAsync(对象参数) 第 55 行
[异步调用]
UI.exe !UI.Commands.AsyncCommandBase.Execute(对象参数) 第 15 行
调用堆栈:
mscorlib.dll !System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task 任务) 第 180 行
mscorlib.dll !System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task 任务) 第 170 行
mscorlib.dll !System.Runtime.CompilerServices.TaskAwaiter.GetResult() 第 125 行
UI.exe !UI.Commands.AsyncCommandFactory.Create(System.Threading.CancellationToken token) 第 27 行
[恢复异步方法]
...
调用堆栈:
mscorlib.dll !System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task 任务) 第 180 行
mscorlib.dll !System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task 任务) 第 170 行
mscorlib.dll !System.Runtime.CompilerServices.TaskAwaiter.GetResult() 第 125 行
UI.exe !UI.NotifyTaskCompletion.WatchTaskAsync(System.Threading.Tasks.Task 任务) 第 66 行
[恢复异步方法]
...
void CurrentStep.Process(CancellationToken cancellationToken)
{
throw new Exception();
}
Run Code Online (Sandbox Code Playgroud)
要了解问题的背景和接受的答案,您需要查看以下文章:
\n\n\n我不想\xe2\x80\x99 不想将异常直接传播回主 UI 循环;我想捕获任何异常并设置属性,以便通过数据绑定完成错误处理。
\n
在这种情况下,您真正需要的是一个仅启动异步操作的同步命令,其中异步操作使用(或您编写的某种类似类型)表示。分解这样的操作(分为同步“启动”和异步数据绑定)比尝试将所有操作集中在一起更容易(这也是可能的 - 只是代码不那么短或可重用) ):NotifyTaskCompletion
// Represents the execution of the current step.\nNotifyTaskCompletion ProcessCurrentStepCommandExecution\n{\n get { return _processCurrentStepCommandExecution; }\n set { _processCurrentStepCommandExecution = value; PropertyChanged(); }\n}\n\n...\n\nvar cancellationToken = ...; // Wherever you get this from.\nProcessCurrentStepCommand = new DelegateCommand(() =>\n{\n ProcessCurrentStepCommandExecution = new NotifyTaskCompletion(async () =>\n {\n await Task.Run(() => CurrentStep.Process(cancellationToken));\n\n // I\'m assuming here you only want to move to the next step if there are no errors.\n // Otherwise, this should be in a finally block.\n CurrentStep = CurrentStep.NextStepViewModel;\n });\n});\nRun Code Online (Sandbox Code Playgroud)\n\n编辑:
\n\n我相信您可能会遇到该文章的示例代码中的错误(在 MSDNMag 决定将其全部删除之前,注释中曾经有更新的代码,我正在努力更新代码示例,这是一个令人惊讶的长过程)。如果任务同步完成(出现异常或成功),则会出现该错误;在这种情况下,NotifyTaskCompletion<T>.TaskCompleted将是null.
要解决此问题,请更改构造函数NotifyTaskCompletion<T>:
{\n Task = task;\n if (!task.IsCompleted)\n TaskCompletion = WatchTaskAsync(task);\n}\nRun Code Online (Sandbox Code Playgroud)\n\n对此:
\n\n{\n Task = task;\n TaskCompletion = WatchTaskAsync(task);\n}\nRun Code Online (Sandbox Code Playgroud)\n