是异步/等待适合那些IO和CPU都绑定方法? [英] Is async/await suitable for methods that are both IO and CPU bound?
问题描述
MSDN文档似乎声明异步
和等待
适用于IO密集型任务,而 Task.Run
应该用于CPU密集型任务。
The MSDN documentation appears to state that async
and await
are suitable for IO-bound tasks whereas Task.Run
should be used for CPU-bound tasks.
我正在执行HTTP请求来检索HTML文档,它然后解析的应用程序。我有一个看起来像这样的方法:
I'm working on an application that performs HTTP requests to retrieve HTML documents, which it then parses. I have a method that looks like this:
public async Task<HtmlDocument> LoadPage(Uri address)
{
using (var httpResponse = await new HttpClient().GetAsync(address)) //IO-bound
using (var responseContent = httpResponse.Content)
using (var contentStream = await responseContent.ReadAsStreamAsync())
return await Task.Run(() => LoadHtmlDocument(contentStream)); //CPU-bound
}
时的异步这个好,适合使用的
和等待
,还是我过度使用它吗?
Is this good and suitable use of async
and await
, or am I over-using it?
推荐答案
有两个很好的答案了,但要加我... 0.02
There are two good answers already, but to add my 0.02...
如果你在谈论的消耗的异步操作,异步
/ 等待
作品出色的两个I / O密集型和CPU密集型。
If you're talking about consuming asynchronous operations, async
/await
works excellently for both I/O-bound and CPU-bound.
我觉得MSDN文档确实有向轻微倾斜的生产的异步操作,在这种情况下,你想使用 TaskCompletionSource
(或类似)用于I / O绑定和 Task.Run
为CPU绑定的(或类似)。一旦你创建了最初的工作
包装,这是最好的消耗的由异步
和的await
。
I think the MSDN docs do have a slight slant towards producing asynchronous operations, in which case you do want to use TaskCompletionSource
(or similar) for I/O-bound and Task.Run
(or similar) for CPU-bound. Once you've created the initial Task
wrapper, it's best consumed by async
and await
.
有关特定例如,它真的可以归结为多少时间 LoadHtmlDocument
将采取。如果删除 Task.Run
,你会调用 LoadPage
(可能在用户界面在同一范围内执行它线)。 Windows 8的准则规定,服用任何操作50ms以上应异步
...牢记您的开发机器上50ms的可能不再是客户机上..
For your particular example, it really comes down to how much time LoadHtmlDocument
will take. If you remove the Task.Run
, you will execute it within the same context that calls LoadPage
(possibly on a UI thread). The Windows 8 guidelines specify that any operation taking more than 50ms should be made async
... keeping in mind that 50ms on your developer machine may be longer on a client's machine...
所以,如果你能保证 LoadHtmlDocument
将低于50ms的运行,你可以直接执行它:
So if you can guarantee that LoadHtmlDocument
will run for less than 50ms, you can just execute it directly:
public async Task<HtmlDocument> LoadPage(Uri address)
{
using (var httpResponse = await new HttpClient().GetAsync(address)) //IO-bound
using (var responseContent = httpResponse.Content)
using (var contentStream = await responseContent.ReadAsStreamAsync()) //IO-bound
return LoadHtmlDocument(contentStream); //CPU-bound
}
不过,我会建议 ConfigureAwait
为@svick提到的:
However, I would recommend ConfigureAwait
as @svick mentioned:
public async Task<HtmlDocument> LoadPage(Uri address)
{
using (var httpResponse = await new HttpClient().GetAsync(address)
.ConfigureAwait(continueOnCapturedContext: false)) //IO-bound
using (var responseContent = httpResponse.Content)
using (var contentStream = await responseContent.ReadAsStreamAsync()
.ConfigureAwait(continueOnCapturedContext: false)) //IO-bound
return LoadHtmlDocument(contentStream); //CPU-bound
}
使用 ConfigureAwait
,如果HTTP请求没有立即完成(同步),那么这将(在这种情况下)事业 LoadHtmlDocument
来一个线程池线程>执行不显式调用 Task.Run
With ConfigureAwait
, if the HTTP request doesn't complete immediately (synchronously), then this will (in this case) cause LoadHtmlDocument
to be executed on a thread pool thread without an explicit call to Task.Run
.
如果您有兴趣异步
在这个级别的表现,你应该检查斯蒂芬Toub的的视频和 MSDN文章上学科。他有很多实用的信息。
If you're interested in async
performance at this level, you should check out Stephen Toub's video and MSDN article on the subject. He has tons of useful information.
这篇关于是异步/等待适合那些IO和CPU都绑定方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!