处理在 Task.WhenAll().Wait() 指定超时后完成的任务
Handle tasks which complete after Task.WhenAll().Wait() specified timeout
我正在尝试使用 Task.WhenAll(tasks).Wait(timeout) 来等待任务完成,然后再处理任务结果。
考虑这个例子:
var tasks = new List<Task<Foo>>();
tasks.Add(Task.Run(() => GetData1()));
tasks.Add(Task.Run(() => GetData2()));
Task.WhenAll(tasks).Wait(TimeSpan.FromSeconds(5));
var completedTasks = tasks
.Where(t => t.Status == TaskStatus.RanToCompletion)
.Select(t => t.Result)
.ToList();
// Process completed tasks
// ...
private Foo GetData1()
{
Thread.Sleep(TimeSpan.FromSeconds(4));
return new Foo();
}
private Foo GetData2()
{
Thread.Sleep(TimeSpan.FromSeconds(10));
// How can I get the result of this task once it completes?
return new Foo();
}
这些任务之一可能无法在 5 秒超时内完成执行。
是否可以以某种方式处理在指定超时后完成的任务的结果?也许我在这种情况下没有使用正确的方法?
编辑:
我正在尝试获取在指定超时时间内完成的所有任务结果。在 Task.WhenAll(tasks).Wait(TimeSpan.FromSeconds(5)):
之后可能会有以下结果
- 第一个任务在 5 秒内完成。
- 第二个任务在 5 秒内完成。
- 两项任务都在 5 秒内完成。
- None 个任务在 5 秒内完成。是否有可能获得 5 秒内未完成但稍后完成的任务结果,比如说 10 秒后?
而不是 Waitall,您可能只想做一些 5 秒的 Spin/sleep,然后像上面那样查询列表。
然后您应该能够在几秒钟后再次枚举以查看还完成了什么。
如果性能是一个问题,您可能需要额外的 'wrapping' 来查看所有任务是否在 5 秒之前完成。
最后在删除他答案的用户的帮助下,我得到了这个解决方案:
private const int TimeoutInSeconds = 5;
private static void Main(string[] args)
{
var tasks = new List<Task>()
{
Task.Run( async() => await Task.Delay(30)),
Task.Run( async() => await Task.Delay(300)),
Task.Run( async() => await Task.Delay(6000)),
Task.Run( async() => await Task.Delay(8000))
};
Task.WhenAll(tasks).Wait(TimeSpan.FromSeconds(TimeoutInSeconds));
var completedTasks = tasks
.Where(t => t.Status == TaskStatus.RanToCompletion).ToList();
var incompleteTasks = tasks
.Where(t => t.Status != TaskStatus.RanToCompletion).ToList();
Task.WhenAll(incompleteTasks)
.ContinueWith(t => { ProcessDelayedTasks(incompleteTasks); });
ProcessCompletedTasks(completedTasks);
Console.ReadKey();
}
private static void ProcessCompletedTasks(IEnumerable<Task> delayedTasks)
{
Console.WriteLine("Processing completed tasks...");
}
private static void ProcessDelayedTasks(IEnumerable<Task> delayedTasks)
{
Console.WriteLine("Processing delayed tasks...");
}
我认为在
之间可能会丢失任务物品
var completedTasks = tasks.Where(t => t.Status == TaskStatus.RanToCompletion).ToList();
和
var incompleteTasks = tasks.Where(t => t.Status != TaskStatus.RanToCompletion).ToList();
因为有些任务可能会在这段时间内运行完成。
作为解决方法(虽然不正确),您可以交换这些行。在这种情况下,某些任务可能会出现在每个(已完成任务和未完成任务)列表中。但也许这总比完全迷失要好。
用于比较已启动任务的数量以及 completedTasks 和 incompleteTasks 列表中的任务数量的单元测试也可能有用。
我正在尝试使用 Task.WhenAll(tasks).Wait(timeout) 来等待任务完成,然后再处理任务结果。
考虑这个例子:
var tasks = new List<Task<Foo>>();
tasks.Add(Task.Run(() => GetData1()));
tasks.Add(Task.Run(() => GetData2()));
Task.WhenAll(tasks).Wait(TimeSpan.FromSeconds(5));
var completedTasks = tasks
.Where(t => t.Status == TaskStatus.RanToCompletion)
.Select(t => t.Result)
.ToList();
// Process completed tasks
// ...
private Foo GetData1()
{
Thread.Sleep(TimeSpan.FromSeconds(4));
return new Foo();
}
private Foo GetData2()
{
Thread.Sleep(TimeSpan.FromSeconds(10));
// How can I get the result of this task once it completes?
return new Foo();
}
这些任务之一可能无法在 5 秒超时内完成执行。
是否可以以某种方式处理在指定超时后完成的任务的结果?也许我在这种情况下没有使用正确的方法?
编辑:
我正在尝试获取在指定超时时间内完成的所有任务结果。在 Task.WhenAll(tasks).Wait(TimeSpan.FromSeconds(5)):
之后可能会有以下结果- 第一个任务在 5 秒内完成。
- 第二个任务在 5 秒内完成。
- 两项任务都在 5 秒内完成。
- None 个任务在 5 秒内完成。是否有可能获得 5 秒内未完成但稍后完成的任务结果,比如说 10 秒后?
而不是 Waitall,您可能只想做一些 5 秒的 Spin/sleep,然后像上面那样查询列表。
然后您应该能够在几秒钟后再次枚举以查看还完成了什么。
如果性能是一个问题,您可能需要额外的 'wrapping' 来查看所有任务是否在 5 秒之前完成。
最后在删除他答案的用户的帮助下,我得到了这个解决方案:
private const int TimeoutInSeconds = 5;
private static void Main(string[] args)
{
var tasks = new List<Task>()
{
Task.Run( async() => await Task.Delay(30)),
Task.Run( async() => await Task.Delay(300)),
Task.Run( async() => await Task.Delay(6000)),
Task.Run( async() => await Task.Delay(8000))
};
Task.WhenAll(tasks).Wait(TimeSpan.FromSeconds(TimeoutInSeconds));
var completedTasks = tasks
.Where(t => t.Status == TaskStatus.RanToCompletion).ToList();
var incompleteTasks = tasks
.Where(t => t.Status != TaskStatus.RanToCompletion).ToList();
Task.WhenAll(incompleteTasks)
.ContinueWith(t => { ProcessDelayedTasks(incompleteTasks); });
ProcessCompletedTasks(completedTasks);
Console.ReadKey();
}
private static void ProcessCompletedTasks(IEnumerable<Task> delayedTasks)
{
Console.WriteLine("Processing completed tasks...");
}
private static void ProcessDelayedTasks(IEnumerable<Task> delayedTasks)
{
Console.WriteLine("Processing delayed tasks...");
}
我认为在
之间可能会丢失任务物品var completedTasks = tasks.Where(t => t.Status == TaskStatus.RanToCompletion).ToList();
和
var incompleteTasks = tasks.Where(t => t.Status != TaskStatus.RanToCompletion).ToList();
因为有些任务可能会在这段时间内运行完成。
作为解决方法(虽然不正确),您可以交换这些行。在这种情况下,某些任务可能会出现在每个(已完成任务和未完成任务)列表中。但也许这总比完全迷失要好。
用于比较已启动任务的数量以及 completedTasks 和 incompleteTasks 列表中的任务数量的单元测试也可能有用。