繁体   English   中英

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

[英]How does the runtime know when to spawn a thread when using “await”?

编辑

我接受了乔恩的评论并重新审视了整个事情。 事实上,它阻塞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的线程。 如果等待已经完成,它就会继续运行; 如果等待还没有完成,它只是告诉等待实例添加一个延续 (通过一个相当复杂的状态机)。 正在完成事情完成时,将调用continuation(通常通过sync-context,如果有的话 - 在标记工作完成的线程上同步)。 然而! 理论上,sync-context可以选择将事物推送到线程池(大多数UI同步上下文,但是,将事物推送到UI线程)。

我想你会发现这个主题很有趣: C#5.0的async-await功能与TPL有什么不同?

简而言之, await不会启动任何线程。

它的作用就是将代码“拆分”到一个位置,比如说,放置'await'所在的行,以及该行作为继续添加到Task的所有内容

注意任务。 请注意,你有Factory.StartNew 因此,在您的代码中,实际启动任务的是工厂 - 它包括将其放在某个线程上,无论是UI还是池还是任何其他任务调度程序。 这意味着,当您执行await时,“任务” 通常已分配给某个调度程序。

当然,它不必分配,也不必开始。 唯一重要的是你需要有一个任务,任何,真的。

如果任务未启动 - await不关心。 它只是附加延续,由您决定以后启动任务。 并将其分配给适当的调度程序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM