被叫方发生了什么';同步调用异步函数时的s线程
本文关键字:函数 异步 调用 线程 同步 发生了 什么 | 更新日期: 2023-09-27 18:21:12
在下面的示例中,当异步"Process"函数被同步调用时,我可以看到对"await Task.Delay(1000)"的调用导致UI挂起。
我知道我可以通过调用"wait Task.Delay(1000).ConfigureAwait(false)"或将"Process"调用封装在另一个任务中来避免挂起。我可以理解同步上下文的问题,我知道await在做一些奇特的事情,也就是说,如果我将调用"Wait Task.Delay(1000)"替换为"Task.Delary(1000).Wait()",UI就不会挂起。
有人能解释一下这种行为吗(我确实试过查看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线程上启动了任务,所以调度程序会尝试在UI线程中调度Process
方法。但是UI线程被Result
getter调用阻塞,因此return "";
语句永远不会执行。