【发布时间】:2021-10-25 08:30:45
【问题描述】:
我有两个任务组,我想在 ASP.NET 应用程序中一个接一个地运行。
isLogin = false;
Task[] firstBatch =
{
new Task(async () => isLogin = await webserviceclient.Login())
};
firstBatch.ForEach(t => t.Start());
Task.WaitAll(firstBatch);
Task[] secondBatch =
{
new Task(async () => UsersList1 = isLogin ? await webserviceclient.GetAllUsers(1) : null),
new Task(async () => UsersList2 = isLogin ? await webserviceclient.GetAllUsers(2) : null)
};
secondBatch.ForEach(t => t.Start());
Task.WaitAll(secondBatch);
在webserviceclient.Login() 中,我已经调用了await _client.GetAsync(_baseUri).ConfigureAwait(false)。至于webserviceclient.GetAllUsers(),我做什么都没关系,因为它从不运行。我想在 await _client.GetAsync(_baseUri) 被称为 firstBatch[0].IsCompleted for unknown reason 之后设置为 true 并且 secondBatch 开始执行。 await _client.GetAsync(_baseUri) 在Task.WaitAll(secondBatch); 命令之后实际上停止等待。这显然不是我想要的。
看起来像是某种死锁,但我看不出问题出在哪里。
【问题讨论】:
-
手动创建大量
Tasks,分别Starting它们并混合async/await。通常是解决问题的方法。我强烈怀疑,如果您在运行时检查所有实际类型,您会发现某些您认为很简单的项目Tasks 实际上是Task<Task>- 所以当外部任务完成时,它没有说明内部任务是否任务是。 -
您可以尝试从您的调用 API 中删除
ConfigureAwait,因为文档说该任务包含在另一个任务中。 -
永远不要使用
new Task,除非您完全清楚自己在做什么,否则这是您的问题以及您将异步 lambda 传递给 Action 的事实将在未观察到的情况下运行,而是使用Task.Run -
任务不是线程。调用
.Start()开始的冷任务从来没有任何充分的理由。webserviceclient.Login()已经返回一个任务。如果您想登录多个服务,您可以将这些 任务放入一个列表并使用var loginResults=Task.WhenAll(tasks)等待所有这些任务并 检查它们的结果。您当前的代码甚至没有这样做,因为isLogin的值是任意的——它将是最后一个要完成的任务返回的值。甚至不是数组中的最后一个任务
标签: c# asp.net async-await task-parallel-library