是异步/等待适合那些IO和CPU都绑定方法? [英] Is async/await suitable for methods that are both IO and CPU bound?

查看:448
本文介绍了是异步/等待适合那些IO和CPU都绑定方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆