【发布时间】:2014-11-01 04:40:03
【问题描述】:
我想在设置超时的同时触发几个任务。我们的想法是从不计其数的任务中收集结果,并取消(甚至忽略)其他任务。
我尝试按照 here 的说明使用扩展方法 WithCancellation,但是抛出异常导致 WhenAll 返回并且不提供任何结果。
这是我尝试过的,但我也向其他方向开放(但请注意,我需要使用 await 而不是 Task.Run,因为我需要任务中的 httpContext):
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(3));
IEnumerable<Task<MyResults>> tasks =
from url in urls
select taskAsync(url).WithCancellation(cts.Token);
Task<MyResults>[] excutedTasks = null;
MyResults[] res = null;
try
{
// Execute the query and start the searches:
excutedTasks = tasks.ToArray();
res = await Task.WhenAll(excutedTasks);
}
catch (Exception exc)
{
if (excutedTasks != null)
{
foreach (Task<MyResults> faulted in excutedTasks.Where(t => t.IsFaulted))
{
// work with faulted and faulted.Exception
}
}
}
// work with res
编辑: 在下面@Servy 的回答之后,这是我使用的实现:
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(3));
IEnumerable<Task<MyResults>> tasks =
from url in urls
select taskAsync(url).WithCancellation(cts.Token);
// Execute the query and start the searches:
Task<MyResults>[] excutedTasks = tasks.ToArray();
try
{
await Task.WhenAll(excutedTasks);
}
catch (OperationCanceledException)
{
// Do nothing - we expect this if a timeout has occurred
}
IEnumerable<Task<MyResults>> completedTasks = excutedTasks.Where(t => t.Status == TaskStatus.RanToCompletion);
var results = new List<MyResults>();
completedTasks.ForEach(async t => results.Add(await t));
【问题讨论】:
-
taskAsync是做什么的? -
在我的情况下,他们使用 httpClient 检索信息,但是我认为任何异步任务都可以(您在下面提供的任务应该可以)。关键是 taskAsync 没有收到取消令牌。
标签: c# asynchronous timeout task .net-4.5