亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為復雜的 Task.WhenAll 添加超時

為復雜的 Task.WhenAll 添加超時

C#
ibeautiful 2022-12-24 09:51:58
我有一個運行異步任務的任務收集器(評論的那個):public Task<ResultOrException<T>[]> WhenAllOrException<T>(IEnumerable<Task<T>> tasks){    return Task.WhenAll(        tasks.Select(            task => task.ContinueWith(                t => t.IsFaulted                    ? new ResultOrException<T>(t.Exception)                    : new ResultOrException<T>(t.Result))));       }public class ResultOrException<T>{    public ResultOrException(T result)    {        IsSuccess = true;        Result = result;    }    public ResultOrException(Exception ex)    {        IsSuccess = false;        Exception = ex;    }    public bool IsSuccess { get; }    public T Result { get; }    public Exception Exception { get; }} 此代碼等待所有任務,即使它們在 2 分鐘后返回。我需要忽略所有超時為五秒的任務返回。我也試過以這種方式更改我的代碼,但它不會編譯: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));或這個: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);如何做到這一點?
查看完整描述

1 回答

?
慕標琳琳

TA貢獻1830條經驗 獲得超9個贊

它不會編譯


這是因為Task.Delay返回一個Task. 那里沒有價值或例外。所以它不能直接與ResultOrException<T>.


您需要決定如何向呼叫者報告超時。如果你想要Task<ResultOrException<T>[]>錯誤,那么你可以這樣做:


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;

}

或者,如果你想返回一個數組ResultOrException<T>,每個數組都有超時錯誤,那么你可以這樣做:


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;

}

或者,如果您想返回及時到達的結果,并且只返回那些沒有及時到達的結果的超時異常,那么您想要將內部WhenAny 移動WhenAll:


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);

        }

    }

}

旁注:您應該始終將 a 傳遞TaskSchedulerContinueWith. 另外,我有一個可能有用的Try實現。


查看完整回答
反對 回復 2022-12-24
  • 1 回答
  • 0 關注
  • 233 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號