wpf C#混合使用Task和Dispatcher.Invoke,为什么会停止?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15500398/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# mixed use of Task and Dispatcher.Invoke, why it halts?
提问by David
I tried below snippet:
我试过下面的片段:
public Task RunUiTask(Action action)
{
var task = Task.Factory.StartNew(() =>
{
Dispatcher.Invoke(DispatcherPriority.Background, action);
});
return task;
}
private void OnCreateTask(object sender, RoutedEventArgs e)
{
var task = RunUiTask(() =>
{
for(int i=0;i<10;i++)
{
ResultTextBlock.Text += i.ToString();
}
});
task.Wait(); //(a) Program stopped here
ResultTextBlock.Text += "Finished"; //(b) Never called;
}
I couldn't understand why, when OnCreateTask (a button click event handler) is called, the program halts at (a), and (b) is never called.
我不明白为什么当 OnCreateTask(按钮单击事件处理程序)被调用时,程序在 (a) 处停止,而 (b) 从未被调用。
Note: I know I can use Dispatcher.BeginInvoke to make program responsive, but this is not my concern here.
注意:我知道我可以使用 Dispatcher.BeginInvoke 来使程序响应,但这不是我关心的问题。
Can any body tell why the program halts at (a), and why (b) is never called? Thanks.
任何人都可以说出为什么程序在 (a) 处停止,为什么 (b) 从未被调用?谢谢。
回答by Noffls
The call of
的呼唤
Dispatcher.Invoke(DispatcherPriority.Background, action);
will execute Actionin your UI Thread and will return after Actionis executed.
The Problem is, that your UI Thead is blocked because of the task.Wait()in your OnCreateTask, so the Action will never be executed and you have a Deadlock.
将Action在您的 UI 线程中执行,并在Action执行后返回。问题是,你的 UI Thead 被阻止了,因为task.Wait()你的OnCreateTask,所以 Action 永远不会被执行并且你有一个死锁。
EDIT
编辑
Instead of your task.Wait()you should use a Continuation and Update ResultTextBlock.Text
task.Wait()您应该使用 Continuation 和 Update而不是您ResultTextBlock.Text
task.ContinueWith(t=>{
ResultTextBlock.Text += "Finished";
}, TaskScheduler.FromCurrentSynchronizationContext());

