我有一個Task
,我開始並希望等待在WPF應用程序中完成。在這個任務中,我調用調度器上的Action
。Task.Wait vs Task.RunSyncronously任務調用WPF Dispatcher.Invoke
如果我使用Task.Wait()
它似乎掛起,就好像該方法從未完成。此外,Dispatcher.Invoke內的斷點永遠不會被命中。
如果我使用Task.RunSyncronously()
它看起來工作正常,分派器內的斷點被擊中。
爲什麼會有差異?
代碼示例如下:
public void ExampleMethod()
{
// When doing the following:
var task = new Task(LoadStuff);
// This never returns:
task.Start();
task.Wait();
// This version, however, does:
task.RunSyncronously();
}
private void LoadStuff()
{
ObservableCollection<StuffObj> stuff = Stuff.Load(arg1, true);
DispatchHelper.RunOnDispatcher(() =>
{
...
});
}
public static class DispatchHelper
{
public static void RunOnDispatcher(Action action)
{
Application.Current.Dispatcher.Invoke(action);
}
}
難道你不是指.NET 4.5,還沒有.NET 5。此外,異步方法生成狀態機而不是使用ContinueWith。 –
@BrianReichle我的意思是C#,而不是.NET,但是,這是錯誤的。就「異步」而言,它確實生成了一個狀態機,並且該狀態機將自身添加爲正在等待的任務的延續。狀態機是一種機制,它可以在繼續運行時知道如何選擇停止的位置,但是對正在等待的任務添加延續是它在「Task」完成時如何運行*任何事情*。 – Servy
狀態機通過'GetAwaiter()'而不是'ContinueWith'返回的awaiter重新計劃(這允許我們等待除了任務之外的其他事情)。它們都調用通用的實現,但是task.GetAwaiter()。OnCompleted(...)不調用ContinueWith(特別是前者避免了創建新任務)。但我想這只是迂腐,大多數人不會關心實現細節:) –