C# 任务 ContinueWith 未按预期工作

C# Task ContinueWith Not Working as Expected

如何等到上一个方法完成后再继续执行?我以为这很容易,但事实并非如此。尽管我已经阅读了很多示例,但我一定是在做一些非常愚蠢的事情。在下面的代码中,我不能让 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

我不羡慕你,因为这看起来是一个非常糟糕的代码库,只是这几行存在多个问题。

其中最大的一个是你不应该 运行 CPU-绑定工作使用 Task.Run 在 ASP.NET.这是 what Stephen Cleary writes about this:

Async and await on ASP.NET are all about I/O. They really excel at reading and writing files, database records, and REST APIs. However, they’re not good for CPU-bound tasks. You can kick off some background work by awaiting Task.Run, but there’s no point in doing so. In fact, that will actually hurt your scalability by interfering with the ASP.NET thread pool heuristics. If you have CPU-bound work to do on ASP.NET, your best bet is to just execute it directly on the request thread. As a general rule, don’t queue work to the thread pool on ASP.NET.

(我推荐阅读 his articles,因为它是 async/await 知识的极好来源。)

因此您的代码已清理:

ut.ModelJSON = _userTransactionService.ConvertToModelJson(typeof(UserDocument).Name, "", transactionDocs);
_genericUploadService.AddUserDocuments(ut, docs);
List<GenericUploadDocumentViewModel> viewModel = GetDocVM();
return Json(viewModel, JsonRequestBehavior.AllowGet);

但是,我怀疑 _genericUploadService.AddUserDocumentsGetDocVM 做了一些 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);