1

我想知道如何最好地处理这个异步等待链,其中需要在异步链之后顺序调用多个 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");
        }
    }
}
4

1 回答 1

2

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

在这种情况下(您的方法受 CPU 限制),制作它们没有任何好处async。您仍然会使用Task.Run. 由于它们应该按顺序执行,因此最简单的方法是同步调用它们,就像您的代码当前正在执行的操作一样。

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

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

于 2013-03-14T22:15:46.817 回答