编辑
我接受了乔恩的评论,并重试了整个过程。实际上,它是阻止了UI线程。我一定以某种方式弄乱了我的初试。在 SomeAsync
完成后,将字符串“OnResume exits”写入。如果将方法更改为使用await Task.WhenAll(t)
,它将(按预期方式)不阻塞。感谢您的输入!
我最初考虑删除问题是因为最初的假设是错误的,但是我认为答案中包含了不应丢失的宝贵信息。
原始帖子:
试图了解async-await的更深层次的内部结构。下面的示例来自使用Xamarin的Android应用。 OnResume()
在UI线程上执行。
SomeAsync()
启动一个新任务(=它产生一个线程)。然后,它使用Task.WaitAll()
执行阻止等待(如果不使用WhenAll()
是更好的选择,那么现在不讨论)。 Task.WaitAll()
运行时UI并未被阻塞。因此SomeAsync()
不在UI线程上运行。这意味着创建了一个新线程。 await
如何“知道”必须在此处生成线程-它将始终这样做吗?如果我将WaitAll()
更改为WhenAll()
,则不需要像我所理解的那样快的其他线程。// This runs on the UI thread.
async override OnResume()
{
// What happens here? Not necessarily a new thread I suppose. But what else?
Console.WriteLine ("OnResume is about to call an async method.");
await SomeAsync();
// Here we are back on the current sync context, which is the UI thread.
SomethingElse();
Console.WriteLine ("OnResume exits");
}
Task<int> SomeAsync()
{
var t = Task.Factory.StartNew (() => {
Console.WriteLine("Working really hard!");
Thread.Sleep(10000);
Console.WriteLine("Done working.");
});
Task.WhenAll (t);
return Task.FromResult (42);
}
最佳答案
简单:从不不会为await
生成线程。如果等待已完成,它将继续运行;否则,它将继续运行。如果awaitable尚未完成,它只是告诉awaitable实例添加一个延续(通过相当复杂的状态机)。当完成的事物完成时,它将调用继续(通常通过sync-context,如果有的话,否则,则在标记该工作已完成的线程上同步)。然而!从理论上讲,sync-context可以是选择将内容推送到线程池中的(大多数UI sync-contexts则将内容推送到UI线程)。
关于c# - 使用 “await”时,运行时如何知道何时生成线程?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22804053/