Async Task.WhenAll with timeout

Is there a way in the new async dotnet 4.5 library to set a timeout on the Task.WhenAll method. I want to fetch several sources and stop after say 5 seconds and skip the sources that weren't finished.


You could combine the resulting Task with a Task.Delay() using Task.WhenAny() :

await Task.WhenAny(Task.WhenAll(tasks), Task.Delay(timeout));

If you want to harvest completed tasks in case of a timeout:

var completedResults =
  tasks
  .Where(t => t.Status == TaskStatus.RanToCompletion)
  .Select(t => t.Result)
  .ToList();

I think a clearer, more robust option that also does exception handling right would be to use Task.WhenAny on each task together with a timeout task, go through all the completed tasks and filter out the timeout ones, and use await Task.WhenAll() instead of Task.Result to gather all the results.

Here's a complete working solution:

static async Task<TResult[]> WhenAll<TResult>(IEnumerable<Task<TResult>> tasks, TimeSpan timeout)
{
    var timeoutTask = Task.Delay(timeout).ContinueWith(_ => default(TResult));
    var completedTasks = 
        (await Task.WhenAll(tasks.Select(task => Task.WhenAny(task, timeoutTask)))).
        Where(task => task != timeoutTask);
    return await Task.WhenAll(completedTasks);
}

Check out the "Early Bailout" and "Task.Delay" sections from Microsoft's Task-Based Asynchronous Pattern Overview.

Early bailout. An operation represented by t1 can be grouped in a WhenAny with another task t2, and we can wait on the WhenAny task. t2 could represent a timeout, or cancellation, or some other signal that will cause the WhenAny task to complete prior to t1 completing.

链接地址: http://www.djcxy.com/p/39528.html

上一篇: CTP安装失败

下一篇: 异步Task.WhenAll超时