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
方式。
事实上,我问的是 使用线程 运行 块方法 和 直接 运行 之间有什么区别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.0IAsyncResult
解决方案,我们可能认为它只是为ExecuteReader
调用Delegate.BeginInvoke
,这将是简单的解决方案,并且最终也会使用池线程。但是如果你调查 BeginExecuteReaderInternal 你会发现它也在内部使用任务。自从 .NET 4.0 中引入任务以来,它肯定已经被重构。
顺便说一句,您也可以通过 TaskFactory
:
IAsyncResult
方法
await Task.Factory.FromAsync(BeginExecuteReader(...));
这不会创建任何额外的线程(在 Begin...
方法创建的线程之上,如果有的话)只是将 IAsyncResult
变成可等待的 Task
方式。