运行时如何知道何时使用"await"生成线程?

Kru*_*lur 6 c# async-await

编辑

我接受了乔恩的评论并重新审视了整个事情.事实上,它阻塞UI线程.我必须以某种方式弄乱我的初步测试.字符串"OnResume exits" SomeAsync完成写入.如果方法被更改为使用await Task.WhenAll(t)它将(如预期)不阻止.感谢您的投入!我首先考虑删除这个问题,因为最初的假设是错误的,但我认为答案包含了不应丢失的有价值的信息.

原帖:

试图了解async-await更深入的内部结构.以下示例来自使用Xamarin的Android应用.OnResume()在UI线程上执行.

  • SomeAsync()开始一个新任务(=它产生一个线程).然后它Task.WaitAll()用于执行阻塞等待(如果WhenAll()是更好的选择,现在不讨论).
  • 我可以看到UI在Task.WaitAll()运行时没有被阻止.所以SomeAsync()不在UI线程上运行.这意味着创建了一个新线程.

如何await"知道"它必须在这里产生一个线程 - 它会一直这样做吗?如果我改变了WaitAll()to 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);
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ell 6

简单:它永远不会产生一个线程await.如果等待已经完成,它就会继续运行; 如果等待还没有完成,它只是告诉等待实例添加一个延续(通过一个相当复杂的状态机).当正在完成事情完成时,将调用continuation(通常通过sync-context,如果有的话 - 在标记工作完成的线程上同步).然而!理论上,sync-context可以选择将事物推送到线程池(大多数UI同步上下文,但是,将事物推送到UI线程).