"async"在单独的线程中运行吗?

12

当我调用foo()方法时,该方法是否在单独的线程上运行?

public async Task<bool> foo(){
  //Some code 
}

没有线程。 - René Vogt
请查看以下帖子。 - CaveCoder
1
根据当前线程的_SynchronizationContext_以及您在该方法内部执行的操作,特别是您等待的其他异步调用以及是否使用.ConfigureAwait(false)等待它们,可能会导致该方法在不同的线程上被_恢复_(在等待之后),但它会在调用者的线程上同步运行。 - René Vogt
3个回答

13
不,它不会。它可能会在内部启动另一个线程并返回该任务,但一般来说它不会在任何线程上运行。
让我解释一下。异步的一般用法是如果你不受CPU限制,也就是说,IO和所有在Windows中的IO在最低层都有回调操作接口,因此,网络请求发送请求后便继续进行其他工作——但是没有线程附着。一般情况下,异步的用例是异步在一个线程上运行,并且当没有要执行的任务时,将使用线程来完成任务,允许在一个线程上执行多个操作,而且IO不会占用线程。
您的方法基本上变成了一个状态引擎,将控制权交给任务调度程序,等待已完成任务的信号。

3
使用 async 关键字并不意味着会创建另一个线程。如果 CLR 发现你在 async 方法中使用 await 调用的方法存在延迟,它会退出该方法,等待已等待的方法完成,然后使用另一个线程继续执行该方法。
当调用标记为 async 的方法时,它会在当前线程上同步运行。
因此,可以得出结论,async 不会创建自己的 thread。调用方法的线程用于执行 async 方法,直到找到一个可等待对象。然后,相同的线程继续执行调用方法的剩余部分,在调用的 async 方法中,在返回可等待对象后,继续执行可以在线程池中的线程上执行,这是唯一需要单独的线程的地方。

1
不,这些任务并不意味着有一个单独的线程在运行。如果您的任务需要在其方法体内阻塞另一个异步任务,则当等待阻塞资源时,它可以暂时返回执行,然后返回执行以完成任务。这基本上是 await 关键字的用途。典型的异步任务是等待 I/O 或网络资源在真正的异步操作开始后返回数据的任务。也可能是您的方法本身生成了自己的线程,使其异步,但这真的取决于异步方法本身的实现方式。
在这个页面中找到了一个伟大的解释,在“煮早餐比喻”中: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/ 请注意,可以并行运行任务,这可能会产生单独的线程,但直接调用方法时,默认情况下不会这样做。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接