Task.Run(Foo) 和 Foo Async() 有什么区别?

What different between Task.Run(Foo) and FooAsync()?

事实上,我问的是 使用线程 运行 块方法 直接 运行 之间有什么区别unblock/asynchronous 方法?

GetResponse / GetResponseAsync, ExecuteReader / BeginExecuteReader

表面上看都没有屏蔽程序,但是原理上有什么区别呢?我觉得这其实涉及到对多线程和异步的真正理解。

谢谢。

简短的回答: Task.Run 会将方法分配给池线程,而异步方法只需 return 一个 Task , 但除此之外它可以为所欲为。

稍微详细一点的回答:

没有任何具体的例子,就不可能知道在异步方法中会发生什么。它可能会也可能不会在内部使用线程,或者它可以 'cheat' 并以与常规方法相同的方式阻止调用者 return 最后 Task.FromResult(myResult) 调用某些东西。

实际上 Task.Run 也有 Func<Task>Func<Task<TResult>> 参数的重载,所以如果你知道异步方法作弊(或者尽管它不使用你想要的线程出于某些 well-founded 原因强制执行它),然后您甚至可以在 Task.Run 调用中包装已经异步的方法。

具体例子:

  • Task.Run(() => GetResponse(...)) return 立即未完成 Task 并安排 GetResponse 在池线程上执行。线程完成后,任务将完成。
  • GetResponseAsync(...) return 立即是一个未完成的任务,一旦在底层套接字上收到响应,该任务就会完成。这次没有池线程。
  • Task.Run(() => ExecuteReader(...)): 同第一点
  • BeginExecuteReader:这很有趣。由于它使用 .NET 1.0 IAsyncResult 解决方案,我们可能认为它只是为 ExecuteReader 调用 Delegate.BeginInvoke,这将是简单的解决方案,并且最终也会使用池线程。但是如果你调查 BeginExecuteReaderInternal 你会发现它也在内部使用任务。自从 .NET 4.0 中引入任务以来,它肯定已经被重构。

顺便说一句,您也可以通过 TaskFactory:

等待 IAsyncResult 方法
await Task.Factory.FromAsync(BeginExecuteReader(...));

这不会创建任何额外的线程(在 Begin... 方法创建的线程之上,如果有的话)只是将 IAsyncResult 变成可等待的 Task方式。