在下面的示例中,当异步调用“ Process”函数时,可以看到对“ await Task.Delay(1000)”的调用导致UI挂起。
我知道我可以通过调用“ await Task.Delay(1000).ConfigureAwait(false)”或将“ Process”调用包装在另一个任务中来避免挂起。我可以理解问题在于synchornizationcontext,并且我知道await正在做一些花哨的事情,即如果我将UI的调用“ await Task.Delay(1000)”替换为“ Task.Delay(1000).Wait()”,不挂。
有人可以解释一下这种行为吗(我曾尝试查看ildasm代码,但没有帮助)。非常感谢。
public MainWindow()
{
InitializeComponent();
Loaded += OnLoaded;
}
public async void OnLoaded(object sender, RoutedEventArgs args)
{
var task = Process();
MessageBox.Show(task.Result);
}
public async Task<String> Process()
{
await Task.Delay(1000);
return "";
}
首先,方法总是被同步调用。当OnLoaded
被调用时,它会调用该Process
方法。
该Process
方法调用该Task.Delay
方法并返回Task<string>
对其等待的对象的引用。这意味着await
后面的代码将在以后执行,并且该Process
方法将在此时返回。
该OnLoaded
方法获取Task<string>
对其存储在task
变量中的对象的引用。然后Result
在任务上调用getter。这将阻塞当前线程,直到任务完成。
一秒钟后,该Process
方法尝试继续。因为您是在UI线程上启动任务的,所以调度程序会尝试Process
在UI线程上调度方法。但是UI线程被Result
getter调用阻塞,因此该return "";
语句从不执行。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句