為什麼 WPF Dispatcher.Invoke 不傳播異常?
這是我的假設範例。我有一個非常簡單的帶有一個按鈕的 WPF 視窗。Button.Click 事件有一個類似這樣的處理程序。
Action doit = () => { Action error = () => { throw new InvalidOperationException("test"); }; try { this.Dispatcher.Invoke(error, DispatcherPriority.Normal); } catch (Exception ex) { System.Diagnostics.Trace.WriteLine(ex); throw; } }; doit.BeginInvoke(null, null);我希望異常會被
Trace.WriteLine呼叫擷取並寫下來。相反,不會擷取任何異常並且應用程序會中斷。有人知道發生這種情況的可能解釋嗎?您建議什麼解決方法來擷取由呼叫的委託引發的異常
Dispatcher.Invoke?更新 1:我
throw在異常處理程式碼中添加了一個。我不想真正忽略異常。我的問題的重點是正確處理它。問題是異常處理程式碼永遠不會被執行。請記住,這是一個假設範例。我的真實程式碼看起來不像那樣。另外,假設我無法更改要呼叫的方法中的程式碼。
更新 2:考慮這個類似的例子。我有一個 Windows 窗體視窗,而不是 WPF 視窗。它有一個按鈕,其處理程序幾乎完全相同。唯一的區別在於呼叫程式碼。它是這樣的。
this.Invoke(error);在 Windows 窗體中,執行異常處理程式碼。為什麼有區別?
**更新:**要觀察另一個執行緒中的異常,您想使用 a
Task,將其排隊到Dispatcher執行緒(使用TaskScheduler.FromCurrentSynchronizationContext),然後等待它,如下所示:var ui = TaskScheduler.FromCurrentSynchronizationContext(); Action doit = () => { var error = Task.Factory.StartNew( () => { throw new InvalidOperationException("test"); }, CancellationToken.None, TaskCreationOptions.None, ui); try { error.Wait(); } catch (Exception ex) { System.Diagnostics.Trace.WriteLine(ex); } }; doit.BeginInvoke(null, null);**更新(再次):**由於您的目標是可重用組件,因此我建議您遷移到
Task基於 -based 的介面或其他基於事件SynchronizationContext的非同步模式,而不是將組件基於DispatcherorISynchronizeInvoke。
Dispatcher- 基於組件僅適用於 WPF/Silverlight;ISynchronizeInvoke基於 - 的組件僅適用於 Windows 窗體。SynchronizationContext基於 - 的組件將透明地與 WPF 或 Windows 窗體一起工作,並且(需要做更多工作)ASP.NET、控制台應用程序、Windows 服務等。基於事件的非同步模式是編寫
SynchronizationContext基於組件的舊推薦方式;對於 .NET 3.5 時代的程式碼,它仍然存在。但是,如果您使用的是 .NET 4,則任務並行庫更加靈活、簡潔且功能強大。下面的TaskScheduler.FromCurrentSynchronizationContext用途SynchronizationContext,是編寫需要這種同步的可重用組件的新方法。