我想触发几个任务,同时为它们设置超时。这个想法是收集那些争分夺秒的任务的结果,并取消(甚至忽略)其他任务。
我尝试使用扩展方法 WithCancellation 如所解释的here https://stackoverflow.com/a/25684549/145599,但是抛出异常会导致 WhenAll 返回并且不提供任何结果。
这是我尝试过的,但我也对其他方向持开放态度(但请注意,我需要使用 wait 而不是 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
EDIT:按照下面@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));
如果任何任务未能完成,您是正确的WhenAll
不返回任何结果did完整的,它只是包装了所有失败的聚合异常。幸运的是,您拥有原始的任务集合,因此您可以从那里获得成功完成的结果。
var completedTasks = excutedTasks.Where(t => t.Status == TaskStatus.RanToCompletion);
只需使用它而不是res
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)