【问题标题】:async await calling into multiple synchronous methods异步等待调用多个同步方法
【发布时间】:2013-03-14 21:18:37
【问题描述】:

我想知道如何最好地处理这个异步等待链,其中需要在异步链之后按顺序调用多个 CPU 绑定方法。

我在下面打了一个小例子。

我只是想找出性能最好/副作用最小的模式是什么。我想确保我没有打败异步的好处。我的 Filter 方法不访问任何异步且可等待的内容,因此要使它们异步意味着我必须在调用方法中返回 Task.Run(() => Filter1(criterion)) 或类似于 await Task.Run(() => { 返回事件; });在过滤器方法本身中。采用哪种方式获得最佳实践是个问题。这是大多数讨论停止的地方,所以一个完整的例子和推荐会很好。

有没有 4.5 async await 高手可以给出好的建议?

namespace test
{
    using System.Net;
    using System.Net.Http;
    using System.Threading.Tasks;
    using System.Web.Http;

    public class sampleController : ApiController
    {
        private Service _service;

        public sampleController()
        {
            _service = new Service();
        }

        public async Task<HttpResponseMessage> SomeTask(DiagnosesSearchCriterion criterion)
        {
            return Request.CreateResponse<IEnumerable<Diagnosis>>(HttpStatusCode.OK, await _service.GetDiagnosesByGroup(criterion));
        }
    }

    public class Service
    {
        private Repository _repository;

        public Service()
        {
            _repository = new Repository();
        }
        public async Task<IEnumerable<Diagnosis>> GetDiagnosis(DiagnosesSearchCriterion criterion)
        {
            System.IO.Stream events = await _repository.GetEvents(criterion);

            // Will these block? Should they be async? They are CPU bound... 
            // how to best handle this, they need to be called sequentially in most cases.
            events = Filter1(criterion, events);
            events = Filter2(criterion, events);

            return new Diagnosis[]{};
        }

        public System.IO.Stream Filter1(DiagnosesSearchCriterion criterion, System.IO.Stream events)
        {
            // CPU bound PLINQ and Parallel filtering logic here.....

            return events;
        }

        public System.IO.Stream Filter2(DiagnosesSearchCriterion criterion, System.IO.Stream events)
        {
            // CPU bound PLINQ and Parallel filtering logic here.....
            // ....

            return events;
        }
    }

    public class Repository
    {
        public async Task<System.IO.Stream> GetEvents(DiagnosesSearchCriterion criterion)
        {
            WebClient wc = new WebClient();
            return await wc.OpenReadTaskAsync("http://www.blah.com/stuff");
        }
    }
}

【问题讨论】:

  • Filter1 和 Filter2 会阻塞,是的。我不完全确定你的问题是什么——你能改写一下吗?
  • 是的,如果 Filter1Filter2 受 CPU 限制,则它们应该是“异步”的,因为 await 之后的代码将在主线程上调用(这将是 UI Winform/WPF 应用程序中的线程)
  • 科里。我只是想找出性能最好/副作用最小的模式是什么。我想确保我没有打败异步的好处。我的 Filter 方法不访问任何异步且可等待的内容,因此要使它们异步意味着我必须在调用方法中返回 Task.Run(() => Filter1(criterion)) 或类似 await Task.Run (() => { 返回事件; });在过滤器方法本身中。采用哪种方式获得最佳实践是个问题。这是大多数讨论停止的地方,所以一个完整的例子和推荐会很好。

标签: c# parallel-processing async-await


【解决方案1】:

在服务器端,async 的主要好处是可扩展性 - 也就是说,如果请求只是在等待一些 I/O,线程池线程可以从处理请求中解放出来完成。

在这种情况下(您的方法受 CPU 限制),将它们设为 async 并没有任何好处。通过使用Task.Run,您仍将占用一个线程池线程(并增加少量开销)。由于它们应该按顺序执行,因此最简单的方法是同步调用它们,就像您的代码当前正在执行的那样。

我认为优秀的Async in ASP.NET video 解决了这种情况。请注意,客户端上的相同情况将有不同的处理方式。在客户端,async 的主要好处是响应能力,因此将 CPU 工作投入线程池线程 (Task.Run) 是有意义的,因为这将释放 UI 线程。

(附带说明一下,在服务器上进行并行处理通常不是一个好主意,除非您确定您的用户数量会非常少)。

【讨论】:

猜你喜欢
  • 2015-11-09
  • 1970-01-01
  • 1970-01-01
  • 2013-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多