AsyncAwait会导致意想不到的方法行为,如果从构造函数调用,方法在错误的线程中运行
本文关键字:方法 函数调用 错误 线程 运行 意想不到 如果 AsyncAwait | 更新日期: 2023-09-27 18:13:57
我试图在不冻结GUI线程的情况下执行一些耗时的操作。UpdateSomething
方法在两个地方被调用,一次在我的ViewModel的构造函数中,一次在按钮单击(RelayCommand)。如果通过RelayCommand调用该方法,则该方法在WorkerThread中执行,但当方法调用来自构造函数时,则在主线程(GUI)中运行。
是什么导致了这种奇怪的行为?我通过IntelliTrace仔细检查了几次。
这是正在讨论的方法:
private async void UpdateSomething()
{
var item = await Task.Factory.StartNew(() =>this.DoSomething("I should run async"));
this.TestItem = item;
}
我使用的是WPF和。net 4.5
对于Task
的操作在主线程上运行的情况,最可能的原因是UpdateSomething
方法是从另一个Task
(计划在主线程上运行的Task
)中调用的。在这种情况下,TaskScheduler.Current
是主线程TaskScheduler
,而不是队列工作于线程池的TaskScheduler.Default
。
Task.Factory.StartNew
默认使用TaskScheduler.Current
(您可以通过调用适当的覆盖来更改它的使用),而Task.Run
使用TaskScheduler.Default
。
Task.Factory.StartNew
不玩将与async/await的声明是不正确的,只是一些默认值可能不是你想要的常见情况(这是Task.Run
引入的部分原因)。
:
- http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx
- 为什么是TaskScheduler。当前默认的TaskScheduler?
我之前也遇到过同样的问题。我在这里贴了一个小帖子:
今天我很紧张。我在一个新任务中包装的代码块上使用await/async。无论我做什么,它都会启动任务,但不会等待结果。
经过多次挫折后,我发现使用
await Task.Factory.StartNew
不能很好地发挥await。最后我把它改成了Task。
基本上你需要使用Task。运行,因为await
不能很好地与Task.Factory.StartNew
兼容
这个问题是由@Rene147回答的,但是他删除了他的回答。(不管出于什么原因)
我将简短地改写他所写的:
await/asyncn不能很好地与Task.Factory.StartNew()
兼容。
将Task.Factory.StartNew
替换为Task.Run
,一切都可以正常工作:
private async void UpdateSomething()
{
//not working when call comes from constructor
//var item = await Task.Factory.StartNew(() =>this.DoSomething("I should run async"));
//working
var item = await Task.Run(() =>this.DoSomething("I run async!"));
this.TestItem = item;
}
Rene147也写了一篇关于它的短文。
我很乐意得到更多关于这个问题的信息,但我还是觉得很奇怪。