处理在Task.WhenAll()之后完成的任务.Wait()指定超时

时间:2015-03-18 21:16:57

标签: c# asp.net task-parallel-library

我正在尝试使用Task.WhenAll(任务)。等待(超时)等待任务完成并在该进程任务结果之后。

考虑这个例子:

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(任务)之后可能会有以下结果。等等(TimeSpan.FromSeconds(5)):

  1. 第一项任务在5秒内完成。
  2. 第二项任务在5秒内完成。
  3. 两个任务都在5秒内完成。
  4. 任何任务都不会在5秒内完成。是否有可能在5秒钟内完成尚未完成的任务结果,但是在10秒后完成后可以完成?

2 个答案:

答案 0 :(得分:2)

最后,在删除答案的用户的帮助下,我最终得到了这个解决方案:

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...");
}

答案 1 :(得分:0)

而不是Waitall,你可能只想做一些5秒的旋转/睡眠,然后在你上面查询列表。

然后,您应该能够在几秒钟之后再次枚举以查看其他内容已完成。

如果需要考虑性能,您可能需要额外的“换行”以查看所有任务是否在5秒之前完成。