当前位置 : 主页 > 编程语言 > c语言 >

c# – 将Task.WhenAll用于多个异步和伪异步方法

来源:互联网 收集:自由互联 发布时间:2021-06-25
我的一位同事重构了我们的控制器方法,以便我们所有的IO操作(包括同步操作)都封装在单独的任务中,然后通过Task.WhenAll并行执行所有这些任务.我完全可以理解这个想法:我们使用更多的
我的一位同事重构了我们的控制器方法,以便我们所有的IO操作(包括同步操作)都封装在单独的任务中,然后通过Task.WhenAll并行执行所有这些任务.我完全可以理解这个想法:我们使用更多的线程,但我们所有的IO操作(我们可以有很多)以最慢的速度执行,但我仍然不确定它是否是正确的路径.这是一种有效的方法还是我遗漏了什么?在典型的ASP.Net网站应用程序中使用更多线程的成本是否明显?
这是一些示例代码

public async Task<ActionResult> Foo() {
    var dataATask = _dataARepository.GetDataAsync();
    var dataBTask = Task.Run(_dataBRepository.GetData());
    await Task.WhenAll(dataATask, dataBTask);
    var viewModel = new ViewModel(dataATask.Result, dataBTask.Result);
    return View(viewModel);
}
一般来说,你的代码是正常的 – 它会消耗更多的线程和比原来更多的CPU,但除非你的网站负载很重,否则不太可能对整体性能产生重大影响.显然,你需要自己测量它的特定负载(包括5-10x常规流量的某种压力水平负载).

在Task.Run中包装同步方法不是最佳实践(参见Should I expose asynchronous wrappers for synchronous methods?).它可能对你有用,只要为这种行为交易额外的线程是可以接受的.

如果您只剩下一个同步操作,则可以保持同步,并在同步步骤结束时等待剩下的额外线程:

var dataATask = _dataARepository.GetDataAsync();
var dataBTaskResult = _dataBRepository.GetData();
await Task.WhenAll(dataATask); // or just await dataATask if you have only one.
var viewModel = new ViewModel(dataATask.Result, dataBTaskResult);
网友评论