C# Async Task.WhenAll带超时
在新的async dotnet 4.5库中是否有一种方法可以设置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()组合: 如果要在超时情
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