我的一位同事重构了我们的控制器方法,以便我们所有的IO操作(包括同步操作)都封装在单独的任务中,然后通过Task.WhenAll并行执行所有这些任务.我完全可以理解这个想法:我们使用更多的
这是一些示例代码
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);