C# 向复杂任务添加超时。WhenAll
我有一个运行异步任务的任务收集器(注释的): 当出现异常时的公共任务(IEnumerable tasks) { 返回任务.WhenAll( 任务。选择( task=>task.ContinueWith( t=>t.IsFaulted ?新结果异常(t.异常) :新结果异常(t.Result)); } 公共类结果异常 { 公共结果异常(T结果) { IsSuccess=true; 结果=结果; } 公共结果异常(异常ex) { IsSuccess=false; 例外=例外; } 公共bool IsSuccess{get;} 公共T结果{get;} 公共异常{get;} } 此代码等待所有任务,即使它们在2分钟后返回。 我需要忽略所有返回的任务,超时时间为5秒 我也尝试过以这种方式更改代码,但它无法编译:C# 向复杂任务添加超时。WhenAll,c#,C#,我有一个运行异步任务的任务收集器(注释的): 当出现异常时的公共任务(IEnumerable tasks) { 返回任务.WhenAll( 任务。选择( task=>task.ContinueWith( t=>t.IsFaulted ?新结果异常(t.异常) :新结果异常(t.Result)); } 公共类结果异常 { 公共结果异常(T结果) { IsSuccess=true; 结果=结果; } 公共结果异常(异常ex) { IsSuccess=false; 例外=例外; } 公共bool Is
return Task.WhenAny(Task.WhenAll(
tasks.Select(
task => task.ContinueWith(
t => t.IsFaulted
? new ResultOrException<T>(t.Exception)
: new ResultOrException<T>(t.Result)))
), Task.Delay(2000));
返回Task.WhenAny(Task.WhenAll(
任务。选择(
task=>task.ContinueWith(
t=>t.IsFaulted
?新结果异常(t.异常)
:新结果异常(t.Result)))
),Task.Delay(2000));
或者这个:
var ts = new TimeSpan(1000);
return await Task.WaitAll(
tasks.Select(
task => task.ContinueWith(
t => t.IsFaulted
? new ResultOrException<T>(t.Exception)
: new ResultOrException<T>(t.Result))),
ts);
var ts=新的时间跨度(1000);
return wait Task.WaitAll(
任务。选择(
task=>task.ContinueWith(
t=>t.IsFaulted
?新结果异常(t.异常)
:新结果异常(t.Result)),
ts);
如何做到这一点
它不会编译
这是因为Task.Delay
返回一个Task
。这里没有任何价值或例外。因此,它不能直接与ResultOrException
序列组合
您需要决定如何向来电者报告超时。如果希望任务出现故障,则可以执行以下操作:
public async Task<ResultOrException<T>[]> WhenAllOrException<T>(IEnumerable<Task<T>> tasks)
{
var resultOrExceptions = Task.WhenAll(
tasks.Select(task => ...)
);
var delayTask = Task.Delay(2000);
var completedTask = await Task.WhenAny(resultOrExceptions, delayTask);
if (completedTask == delayTask)
throw new TimeoutException();
return await resultOrExceptions;
}
public async Task<ResultOrException<T>[]> WhenAllOrException<T>(IEnumerable<Task<T>> tasks)
{
var resultOrExceptionTasks = tasks.Select(task => ...)
.ToArray();
var resultOrExceptions = Task.WhenAll(resultOrExceptionTasks);
var delayTask = Task.Delay(2000);
var completedTask = await Task.WhenAny(resultOrExceptions, delayTask);
if (completedTask == delayTask)
return Enumerable.Repeat(new ResultOrException<T>(new TimeoutException()), resultOrExceptionTasks.Length).ToArray();
return await resultOrExceptions;
}
旁注:你应该。另外,我还有一个可能有用的方法。在这种情况下,您应该使用任务。WaitAll
。这是一个稍微不同的用例,但是可以将TimeSpan
添加为超时。您不需要过度设计任务,也不需要将WhenAny
与WhenAll
结合起来。当您调用whenalloreexception
时,是否计划wait
?好的,我忘了插入async/wait,但这不是问题所在。@MichaelPuckettII我喜欢有时间跨度的waitAll解决方案,但使用它可以更改类型结果从“ResultOrException”到“Task”,我需要一个ResultOrException类型返回。@pizzonialesioTask
已经内置了结果/异常。我建议查看Task.Exception
,了解如何通过Task
正确冒泡异常。我知道你在做什么,但我只建议你使用已经在大多数系统中得到验证和实施的标准方法。也许你没有意识到你可以做到这一点,或者你正试图更具体一些,这很好,但这感觉设计过度,可能比它应该的更复杂。查看通过任务冒泡的异常,以及如何正确处理结果和I…。
public async Task<ResultOrException<T>[]> WhenAllOrException<T>(IEnumerable<Task<T>> tasks)
{
var resultOrExceptionTasks = tasks.Select(task => ...)
.ToArray();
var resultOrExceptions = Task.WhenAll(resultOrExceptionTasks);
var delayTask = Task.Delay(2000);
var completedTask = await Task.WhenAny(resultOrExceptions, delayTask);
if (completedTask == delayTask)
return Enumerable.Repeat(new ResultOrException<T>(new TimeoutException()), resultOrExceptionTasks.Length).ToArray();
return await resultOrExceptions;
}
public Task<ResultOrException<T>[]> WhenAllOrException<T>(IEnumerable<Task<T>> tasks)
{
var delayTask = Task.Delay(2000);
return Task.WhenAll(tasks.Select(WithTimeout));
async Task<ResultOrException<T>> WithTimeout(Task<T> task)
{
var completedTask = await Task.WhenAny(task, delayTask);
if (completedTask == delayTask)
return new ResultOrException<T>(new TimeoutException());
try
{
return new ResultOrException<T>(await task);
}
catch (Exception ex)
{
return new ResultOrException<T>(ex);
}
}
}