Async等待调用多个同步方法

本文关键字:同步方法 调用 等待 Async | 更新日期: 2023-09-27 18:03:53

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

我在下面输入了一个小例子。

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

有什么4.5异步等待大师可以给好的建议吗?

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");
        }
    }
}

Async等待调用多个同步方法

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

在这种情况下(您的方法是cpu绑定的),将它们设置为async没有任何好处。通过使用Task.Run,您仍然会占用线程池线程(并增加少量开销)。因为它们应该按顺序执行,所以最简单的方法是同步调用它们,就像您的代码当前所做的那样。

我认为这种情况是解决在优秀的Async在ASP。网络视频。请注意,在客户端处理相同的情况会有所不同。在客户端,async的主要好处是响应性,因此将CPU工作扔到线程池线程(Task.Run)中是有意义的,因为这将释放UI线程。

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