C# Async Task.WhenAll带超时

C# Async Task.WhenAll带超时,c#,.net,async-ctp,async-await,C#,.net,Async Ctp,Async Await,在新的async dotnet 4.5库中是否有一种方法可以设置Task.WhenAll方法的超时。我想获取多个来源,并在5秒钟后停止,跳过尚未完成的来源。查看Microsoft网站的“早期救援”和“任务延迟”部分 提前救助。由t1表示的操作可以分组为 WhenAny有另一个任务t2,我们可以等待WhenAny任务。t2 可能表示超时、取消或其他信号 将导致WhenAny任务在t1完成之前完成 您可以使用Task.WhenAny()将生成的Task与Task.Delay()组合: 如果要在超时情

在新的async dotnet 4.5库中是否有一种方法可以设置
Task.WhenAll
方法的超时。我想获取多个来源,并在5秒钟后停止,跳过尚未完成的来源。

查看Microsoft网站的“早期救援”和“任务延迟”部分

提前救助。由t1表示的操作可以分组为 WhenAny有另一个任务t2,我们可以等待WhenAny任务。t2 可能表示超时、取消或其他信号 将导致WhenAny任务在t1完成之前完成


您可以使用
Task.WhenAny()
将生成的
Task
Task.Delay()
组合:

如果要在超时情况下获取已完成的任务,请执行以下操作:

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

似乎您只需要Task.WaitAll重载和timeout参数—如果它返回true,那么您就知道它们都已完成—否则,您可以在IsCompleted上进行筛选

if (Task.WaitAll(tasks, myTimeout) == false)
{
    tasks = tasks.Where(t => t.IsCompleted);
}
...

我得到了下面的代码,它满足了我的需要:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Net.Http;
using System.Json;
using System.Threading;

namespace MyAsync
{
    class Program
    {
        static void Main(string[] args)
        {
            var cts = new CancellationTokenSource();
            Console.WriteLine("Start Main");
            List<Task<List<MyObject>>> listoftasks = new List<Task<List<MyObject>>>();
            listoftasks.Add(GetGoogle(cts));
            listoftasks.Add(GetTwitter(cts));
            listoftasks.Add(GetSleep(cts));
            listoftasks.Add(GetxSleep(cts));

            List<MyObject>[] arrayofanswers = Task.WhenAll(listoftasks).Result;
            List<MyObject> answer = new List<MyObject>();
            foreach (List<MyObject> answers in arrayofanswers)
            {
                answer.AddRange(answers);
            }
            foreach (MyObject o in answer)
            {
                Console.WriteLine("{0} - {1}", o.name, o.origin);
            }
            Console.WriteLine("Press <Enter>");
            Console.ReadLine();
        } 

        static async Task<List<MyObject>> GetGoogle(CancellationTokenSource cts) 
        {
            try
            {
                Console.WriteLine("Start GetGoogle");
                List<MyObject> l = new List<MyObject>();
                var client = new HttpClient();
                Task<HttpResponseMessage> awaitable = client.GetAsync("http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=broersa", cts.Token);
                HttpResponseMessage res = await awaitable;
                Console.WriteLine("After GetGoogle GetAsync");
                dynamic data = JsonValue.Parse(res.Content.ReadAsStringAsync().Result);
                Console.WriteLine("After GetGoogle ReadAsStringAsync");
                foreach (var r in data.responseData.results)
                {
                    l.Add(new MyObject() { name = r.titleNoFormatting, origin = "google" });
                }
                return l;
            }
            catch (TaskCanceledException)
            {
                return new List<MyObject>();
            }
        }

        static async Task<List<MyObject>> GetTwitter(CancellationTokenSource cts)
        {
            try
            {
                Console.WriteLine("Start GetTwitter");
                List<MyObject> l = new List<MyObject>();
                var client = new HttpClient();
                Task<HttpResponseMessage> awaitable = client.GetAsync("http://search.twitter.com/search.json?q=broersa&rpp=5&include_entities=true&result_type=mixed",cts.Token);
                HttpResponseMessage res = await awaitable;
                Console.WriteLine("After GetTwitter GetAsync");
                dynamic data = JsonValue.Parse(res.Content.ReadAsStringAsync().Result);
                Console.WriteLine("After GetTwitter ReadAsStringAsync");
                foreach (var r in data.results)
                {
                    l.Add(new MyObject() { name = r.text, origin = "twitter" });
                }
                return l;
            }
            catch (TaskCanceledException)
            {
                return new List<MyObject>();
            }
        }

        static async Task<List<MyObject>> GetSleep(CancellationTokenSource cts)
        {
            try
            {
                Console.WriteLine("Start GetSleep");
                List<MyObject> l = new List<MyObject>();
                await Task.Delay(5000,cts.Token);
                l.Add(new MyObject() { name = "Slept well", origin = "sleep" });
                return l;
            }
            catch (TaskCanceledException)
            {
                return new List<MyObject>();
            }

        } 

        static async Task<List<MyObject>> GetxSleep(CancellationTokenSource cts)
        {
            Console.WriteLine("Start GetxSleep");
            List<MyObject> l = new List<MyObject>();
            await Task.Delay(2000);
            cts.Cancel();
            l.Add(new MyObject() { name = "Slept short", origin = "xsleep" });
            return l;
        } 

    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.Threading.Tasks;
使用System.Net.Http;
使用System.Json;
使用系统线程;
名称空间MyAsync
{
班级计划
{
静态void Main(字符串[]参数)
{
var cts=新的CancellationTokenSource();
控制台写入线(“启动主”);
List listoftasks=新列表();
Add(GetGoogle(cts));
Add(GetTwitter(cts));
Add(GetSleep(cts));
Add(GetxSleep(cts));
List[]arrayofanswers=Task.WhenAll(listoftasks).Result;
列表答案=新列表();
foreach(以数组形式列出答案)
{
答案。添加范围(答案);
}
foreach(回答中的MyObject o)
{
WriteLine(“{0}-{1}”,o.name,o.origin);
}
控制台。写线(“按”);
Console.ReadLine();
} 
静态异步任务GetGoogle(CancellationTokenSource cts)
{
尝试
{
Console.WriteLine(“启动GetGoogle”);
列表l=新列表();
var client=新的HttpClient();
任务等待=client.GetAsync(“http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=broersa“,cts.Token);
HttpResponseMessage res=等待等待;
WriteLine(“在GetGoogle GetAsync之后”);
动态数据=JsonValue.Parse(res.Content.ReadAsStringAsync().Result);
Console.WriteLine(“在GetGoogle ReadAsStringAsync之后”);
foreach(data.responseData.results中的var)
{
l、 添加(newmyobject(){name=r.titlenoformating,origin=“google”});
}
返回l;
}
捕获(TaskCanceledException)
{
返回新列表();
}
}
静态异步任务GetTwitter(CancellationTokenSource cts)
{
尝试
{
Console.WriteLine(“启动GetTwitter”);
列表l=新列表();
var client=新的HttpClient();
任务等待=client.GetAsync(“http://search.twitter.com/search.json?q=broersa&rpp=5&include_entities=true&result_type=mixed“,cts.Token);
HttpResponseMessage res=等待等待;
WriteLine(“在GetTwitter GetAsync之后”);
动态数据=JsonValue.Parse(res.Content.ReadAsStringAsync().Result);
Console.WriteLine(“GetTwitter ReadAsStringAsync之后”);
foreach(data.results中的var r)
{
l、 添加(newmyObject(){name=r.text,origin=“twitter”});
}
返回l;
}
捕获(TaskCanceledException)
{
返回新列表();
}
}
静态异步任务GetSleep(CancellationTokenSource cts)
{
尝试
{
Console.WriteLine(“启动GetSleep”);
列表l=新列表();
等待任务延迟(5000,cts.Token);
l、 添加(newmyobject(){name=“sleepwell”,origin=“sleep”});
返回l;
}
捕获(TaskCanceledException)
{
返回新列表();
}
} 
静态异步任务GetxSleep(CancellationTokenSource cts)
{
WriteLine(“启动GetxSleep”);
列表l=新列表();
等待任务。延迟(2000);
cts.Cancel();
l、 添加(newmyobject(){name=“sleepshort”,origin=“xsleep”});
返回l;
} 
}
}
我的解释在我的博客中:

查看中建议的自定义任务组合器

带超时的异步静态任务
(此任务任务,TimeSpan超时)
{
任务赢家=等待(Task.whenay)
(任务,任务延迟(超时));
如果(winner!=任务)抛出新的TimeoutException();
返回等待任务;//展开结果/重新抛出
}

我还没有尝试过。

除了svick的答案外,当我必须等待几项任务完成,但在等待过程中必须处理其他任务时,以下内容对我很有用:

Task[] TasksToWaitFor = //Your tasks
TimeSpan Timeout = TimeSpan.FromSeconds( 30 );

while( true )
{
    await Task.WhenAny( Task.WhenAll( TasksToWaitFor ), Task.Delay( Timeout ) );
    if( TasksToWaitFor.All( a => a.IsCompleted ) )
        break;

    //Do something else here
}

你所描述的似乎是一个非常普遍的需求,但我在任何地方都找不到这样的例子。我找了很多。。。我最终创建了以下内容:

TimeSpan timeout = TimeSpan.FromSeconds(5.0);

Task<Task>[] tasksOfTasks =
{
    Task.WhenAny(SomeTaskAsync("a"), Task.Delay(timeout)),
    Task.WhenAny(SomeTaskAsync("b"), Task.Delay(timeout)),
    Task.WhenAny(SomeTaskAsync("c"), Task.Delay(timeout))
};

Task[] completedTasks = await Task.WhenAll(tasksOfTasks);

List<MyResult> = completedTasks.OfType<Task<MyResult>>().Select(task => task.Result).ToList();
TimeSpan timeout=TimeSpan.FromSeconds(5.0);
Task[]tasksOfTasks=
{
Task.whenny(sometaskaync(“a”)、Task.Delay(timeout)),
Task.whenay(sometaskaync(“b”)、Task.Delay(timeout)),
Task.whenay(sometaskancync(“c”),Task.Delay(超时))
};
Task[]completedTasks=等待Task.WhenAll(TaskSoftTasks);
列表=已完成的任务
Task[] TasksToWaitFor = //Your tasks
TimeSpan Timeout = TimeSpan.FromSeconds( 30 );

while( true )
{
    await Task.WhenAny( Task.WhenAll( TasksToWaitFor ), Task.Delay( Timeout ) );
    if( TasksToWaitFor.All( a => a.IsCompleted ) )
        break;

    //Do something else here
}
TimeSpan timeout = TimeSpan.FromSeconds(5.0);

Task<Task>[] tasksOfTasks =
{
    Task.WhenAny(SomeTaskAsync("a"), Task.Delay(timeout)),
    Task.WhenAny(SomeTaskAsync("b"), Task.Delay(timeout)),
    Task.WhenAny(SomeTaskAsync("c"), Task.Delay(timeout))
};

Task[] completedTasks = await Task.WhenAll(tasksOfTasks);

List<MyResult> = completedTasks.OfType<Task<MyResult>>().Select(task => task.Result).ToList();
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);
}
public static async Task WhenAll(
    IEnumerable<Task> tasks, 
    int millisecondsTimeOut,
    CancellationToken cancellationToken)
{
    using(Task timeoutTask = Task.Delay(millisecondsTimeOut))
    using(Task cancellationMonitorTask = Task.Delay(-1, cancellationToken))
    {
        Task completedTask = await Task.WhenAny(
            Task.WhenAll(tasks), 
            timeoutTask, 
            cancellationMonitorTask
        );

        if (completedTask == timeoutTask)
        {
            throw new TimeoutException();
        }
        if (completedTask == cancellationMonitorTask)
        {
            throw new OperationCanceledException();
        }
        await completedTask;
    }
}
public static async Task WhenAll(this IEnumerable<Task> tasks, TimeSpan timeout)
{
  // Create a timeout task.
  var timeoutTask = Task.Delay(timeout);

  // Get the completed tasks made up of...
  var completedTasks =
  (
    // ...all tasks specified
    await Task.WhenAll(tasks

    // Now finish when its task has finished or the timeout task finishes
    .Select(task => Task.WhenAny(task, timeoutTask)))
  )
  // ...but not the timeout task
  .Where(task => task != timeoutTask);

  // And wait for the internal WhenAll to complete.
  await Task.WhenAll(completedTasks);
}
        var timeoutTime = 10;

        var tasksResult = await Task.WhenAll(
                                listOfTasks.Select(x => Task.WhenAny(
                                    x, Task.Delay(TimeSpan.FromMinutes(timeoutTime)))
                                )
                            );


        var succeededtasksResponses = tasksResult
                                               .OfType<Task<MyResult>>()
                                               .Select(task => task.Result);

        if (succeededtasksResponses.Count() != listOfTasks.Count())
        {
            // Not all tasks were completed
            // Throw error or do whatever you want
        }

        //You can use the succeededtasksResponses that contains the list of successful responses