c# - 如何确保任务已启动并在未启动时安全地启动它?

标签 c# asynchronous async-await task

我得到一个 IEnumerable<Task> tasks从我无法控制的地方。我不知道任务是否是使用 new Task 手动创建的, Task.Run ,或者如果它们是异步方法调用的结果 async Task DoSomethingAsync() .

如果我这样做 await Task.WhenAll(tasks) ,我冒着无限期挂起的风险,因为可能有一个或多个任务没有开始。

我做不到tasks.ForEach(t => t.Start()) ,因为如果它来自异步方法调用(已经启动),那么我将得到一个 InvalidOperationException“可能无法在 promise 式任务上调用启动”。

我做不到await Task.WhenAll(tasks.Select(t => Task.Run(async () => await t)))因为每个 t仍然不能只是等待它开始。

我假设解决方案与检查每个任务的 Status 有关和 Start()基于此,但我也认为这可能很棘手,因为该状态可能随时发生变化,对吗?如果这仍然是可行的方法,检查哪些状态是正确的,我应该担心哪些线程问题?

非工作案例示例:

//making an IEnumerable as an example, remember I don't control this part
Task t = new Task( () => Console.WriteLine("started"));
IEnumerable<Task> tasks = new[] {t};

//here I receive the tasks
await Task.WhenAll(tasks);//waits forever because t is not started

工作案例:

//calls the async function, starting it.
Task t = DoSomethingAsync();
IEnumerable<Task> tasks = new[] {t};

//here I receive the tasks and it will complete because the task is already started
await Task.WhenAll(tasks);

async Task DoSomethingAsync() => Console.WriteLine("started");

最佳答案

如果出于某种原因您无法更改代码以不返回未启动的任务,您可以检查 Status 并启动任务(如果它具有 Created 状态):

if (task.Status == TaskStatus.Created)
   task.Start();

所有其他任务状态表示任务已完成、正在运行或正在安排中,因此您不需要在这些状态下启动任务。

当然,理论上这会引入竞争条件,因为任务可以在您的检查和 Start 调用之间开始,但是,正如 Servy 在评论中正确指出的那样 - 如果这里存在竞争条件 -这意味着另一方(创建该任务)也在尝试启动它。即使您处理异常 (InvalidOperationException) - 另一方也不太可能这样做,因此在尝试开始他们自己的任务时会遇到异常。因此只有一方(您或创建该任务的代码)应该尝试启动它。

就是说 - 比这样做更好的是确保您永远不会首先获得未开始的任务,因为将此类任务返回给外部代码只是糟​​糕的设计,至少没有明确指出(虽然它是为了某些用途可以在内部使用未启动任务的情况)。

关于c# - 如何确保任务已启动并在未启动时安全地启动它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47634841/

相关文章:

java - 将第一个 CompletableFuture 的结果传递给链上的其他 CompletableFuture

java - 是否有java线程中断异步队列并放入alertable?

c# - 使用 BoundField 时对特定 Gridview 列的 JQuery 搜索

c# - 我在哪里可以找到 WPF 应用程序中 UI 的一些主题/演示?

c# - MVVM light application - 如何正确清理 ViewModels

javascript - 如何使用回调操作来自多个异步 ajax 异步调用的数据?

c# - 如何将 visual studio 2010 解决方案构建到独立的 dll 中?

php异步cURL请求

javascript - 调用自身的异步函数

javascript - async 是否使其内部的所有内容都异步?