实际上,我在问使用线程运行阻止方法和直接运行取消阻止/异步方法有什么区别?
例如GetResponse / GetResponseAsync,ExecuteReader / BeginExecuteReader等
表面上,这两个程序都没有阻塞,但是原理上有什么区别?我认为这实际上涉及对多线程和异步的真正理解。
谢谢。
答案 0 :(得分:1)
简而言之: Task.Run
会将方法分配给池线程,而异步方法只需要返回一个Task
,但除此之外,它还能执行任何操作想要。
详细的答案:
没有任何特定的例子,就不可能说出异步方法会发生什么。它可能会或可能不会在内部使用线程,或者可能会“欺骗”并阻止调用方,就像常规方法最后通过Task.FromResult(myResult)
返回内容一样。
实际上Task.Run
也具有Func<Task>
和Func<Task<TResult>>
参数的重载,因此,如果您知道异步方法作弊(或者尽管它不使用线程,则您要强制执行它)出于某些充分的理由),那么您甚至可以在Task.Run
调用中包装已经异步的方法。
至于具体示例:
Task.Run(() => GetResponse(...))
立即返回未完成的Task
,并安排GetResponse
在池线程中执行。线程完成后,任务将完成。GetResponseAsync(...)
立即返回未完成的任务,一旦在基础套接字上收到响应,该任务将完成。这次没有池线程。 Task.Run(() => ExecuteReader(...))
:与第一点相同BeginExecuteReader
:这是一个有趣的话题。由于它使用.NET 1.0 IAsyncResult
解决方案,因此我们可能认为它只是为Delegate.BeginInvoke
调用了ExecuteReader
,这将是微不足道的解决方案,并且最终会使用池线程。但是,如果您调查BeginExecuteReaderInternal,您会发现它还在内部使用任务。自从在.NET 4.0中引入任务以来,它一定已经进行了重构。顺便说一句,您也可以通过IAsyncResult
等待TaskFactory
方法:
await Task.Factory.FromAsync(BeginExecuteReader(...));
这不会创建任何其他线程(在由Begin...
方法创建的线程之上(如果有的话))只是以一种方便的方式将IAsyncResult
变成了可等待的Task
。