Big*_*ddy -1 c# asp.net-mvc task-parallel-library async-await
在继续执行之前如何等待上一个方法完成?我觉得这很容易,但事实并非如此.即使我已经阅读了很多例子,我也必须做一些非常愚蠢的事情.在下面的代码中,我不能让GetDocVM()方法执行,直到AddUserDocuments()方法完成.为什么?因为GetDocVM() 不会引入刚刚添加的记录.我继承了这段代码,并试图改进它.
ut.ModelJSON = await Task.Run(() => _userTransactionService.ConvertToModelJson(typeof(UserDocument).Name, "", transactionDocs)).ConfigureAwait(false);
var taskReturnsVoid = Task.Run(() => _genericUploadService.AddUserDocuments(ut, docs));
List<GenericUploadDocumentViewModel> viewModel = new List<GenericUploadDocumentViewModel>();
await taskReturnsVoid.ContinueWith((t) =>
{
viewModel = GetDocVM();//I EXPECTED THIS TO WAIT TO BE EXECUTED
});
return Json(viewModel, JsonRequestBehavior.AllowGet); //GETTING HERE TOO SOON
Run Code Online (Sandbox Code Playgroud)
我不羡慕你,因为这看起来是一个非常糟糕的代码库,只是这几行遇到了多个问题.
其中一个最大的问题是你不应该在ASP.NET上使用Task.Run来运行CPU限制的工作.这就是斯蒂芬克利里写的:
ASP.NET上的异步和等待都是关于I/O的.他们擅长阅读和编写文件,数据库记录和REST API.但是,它们不适合CPU绑定任务.您可以通过等待Task.Run开始一些后台工作,但这样做没有意义.事实上,这实际上会通过干扰ASP.NET线程池启发式来损害您的可伸缩性.如果你有关于ASP.NET的CPU限制工作,最好的办法是直接在请求线程上执行它.作为一般规则,不要将工作排队到ASP.NET上的线程池.
(我建议阅读他的文章,因为它是异步/等待知识的绝佳来源.)
所以你的代码清理了:
ut.ModelJSON = _userTransactionService.ConvertToModelJson(typeof(UserDocument).Name, "", transactionDocs);
_genericUploadService.AddUserDocuments(ut, docs);
List<GenericUploadDocumentViewModel> viewModel = GetDocVM();
return Json(viewModel, JsonRequestBehavior.AllowGet);
Run Code Online (Sandbox Code Playgroud)
但是,我怀疑_genericUploadService.AddUserDocuments和GetDocVM做了一些与I/O相关的工作(比如网络或数据库访问).如果您想提高代码的性能,您应该考虑将它们重写为异步,然后您可以这样做:
ut.ModelJSON = _userTransactionService.ConvertToModelJson(typeof(UserDocument).Name, "", transactionDocs);
await _genericUploadService.AddUserDocumentsAsync(ut, docs);
List<GenericUploadDocumentViewModel> viewModel = await GetDocVMAsync();
return Json(viewModel, JsonRequestBehavior.AllowGet);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
116 次 |
| 最近记录: |