代码之家  ›  专栏  ›  技术社区  ›  ca9163d9

返回任务的结果-包括异常?

  •  3
  • ca9163d9  · 技术社区  · 6 年前

    以下代码运行 M1 , M2 , M3 , M4 同时。每个方法都可能引发异常。该方法应返回四个异步方法的结果-方法返回的int或异常。

    async Task<string> RunAll()
    {
        int m1result, m2result, m3result, m4result;
        try
        {
            var m1task = M1();
            var m2task = M2();
            var m3task = M3();
            var m4task = M4();
            // await Task.WhenAll(new Task<int>[] { m1task, m2task, m3task, m4task });
            m1result = await m1task;
            m2result = await m2task;
            m3result = await m3task;
            m4result = await m4task;
        }
        catch (Exception ex)
        {
            // need to return the ex of the failed task. How?
        }
        // How to implement M1HasException, M2HasException, ... in the following lines?
        var m1msg = M1HasException ? M1ExceptionMessage : m1result.ToString();
        var m2msg = M2HasException ? M2ExceptionMessage : m2result.ToString();
        var m3msg = M3HasException ? M3ExceptionMessage : m3result.ToString();
        var m4msg = M4HasException ? M4ExceptionMessage : m4result.ToString();
        return $"M1: {m1msg}, M2: {m2msg}, M3: {m3msg}, M4: {m4msg}";
    }
    

    如何捕获失败任务的个别异常?

    例如,如果只有M2抛出异常,

    "M1: 1, M2: Excpetion...., M3: 3, M4: 4"
    
    4 回复  |  直到 6 年前
        1
  •  1
  •   Murray Foxcroft    6 年前

    每个任务都有一个Status和Exception属性。

    您可能希望查看它是否出现故障:

    myTask.Status == TaskStatus.Faulted
    

    或者如果它已经排除:

    if (myTask.Exception != null) 
    

    你可以用 ContinueWhenAll 运行所有任务,然后检查状态。

    See the docs here .

        2
  •  0
  •   Marco Luzzara    6 年前

    正如其他回答/评论所指出的,一种可能的方法是 ContinueWith ContinueWhenAll . 这是个聪明的把戏,因为 Task 拥有 Exception 属性:

    获取导致任务过早结束的AggregateException。 如果任务成功完成或尚未引发任何 异常,这将返回空值。

    使用 继续 无论任务是否成功完成,它都将作为参数传递给委托函数。从那里可以检查是否引发了异常。

    Task<string> GetStringedResult<T>(Task<T> initialTask)
    {
        return initialTask.ContinueWith(t => {
            return t.Exception?.InnerException.Message ?? t.Result.ToString();
        });
    }
    
    async Task<string> RunAll()
    {
        string m1result, m2result, m3result, m4result;
    
        var m1task = GetStringedResult(M1());
        var m2task = GetStringedResult(M2());
        var m3task = GetStringedResult(M3());
        var m4task = GetStringedResult(M4());
    
        m1result = await m1task;
        m2result = await m2task;
        m3result = await m3task;
        m4result = await m4task;
    
        return $"M1: {m1result}, M2: {m2result}, M3: {m3result}, M4: {m4result}";
    }
    
        3
  •  0
  •   Shahar Shokrani    6 年前

    您可以将任务包装在 WaitAll 抓住 AggregateException ( docs ),

    try
    {
        Task.WaitAll(new[] { task1, task2 }, token);
    }
    catch (AggregateException ae)
    {
        foreach (var ex in ae.InnerExceptions)
            //Do what ever you want with the ex.
    }
    
        4
  •  0
  •   Johnny    6 年前

    你能把每个包起来吗 await 在里面 try-catch 阻止并捕获异常消息(如果有的话),似乎是可行的。。。

    var results = new List<string>();
    
    try { results.Add(await t1); } catch { results.Add("Exception"); };
    try { results.Add(await t2); } catch { results.Add("Exception"); };
    try { results.Add(await t3); } catch { results.Add("Exception"); };
    
    return string.Join("|", results);
    

    如果你想用 WhenAll 你可以 等待 对于它并忽略异常,然后执行与上面所示相同的练习来检索单个任务结果。。。

    try { await Task.WhenAll(t1, t2, t3); } catch { };
    //                                      ^^^^^^^^^
    // then same as ^ above