Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 向复杂任务添加超时。WhenAll_C# - Fatal编程技术网

C# 向复杂任务添加超时。WhenAll

C# 向复杂任务添加超时。WhenAll,c#,C#,我有一个运行异步任务的任务收集器(注释的): 当出现异常时的公共任务(IEnumerable tasks) { 返回任务.WhenAll( 任务。选择( task=>task.ContinueWith( t=>t.IsFaulted ?新结果异常(t.异常) :新结果异常(t.Result)); } 公共类结果异常 { 公共结果异常(T结果) { IsSuccess=true; 结果=结果; } 公共结果异常(异常ex) { IsSuccess=false; 例外=例外; } 公共bool Is

我有一个运行异步任务的任务收集器(注释的):

当出现异常时的公共任务(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秒

我也尝试过以这种方式更改代码,但它无法编译:

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类型返回。@pizzonialesio
Task
已经内置了结果/异常。我建议查看
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);
        }
    }
}