返回任务结果 - 包括例外情况?

问题描述 投票:3回答:4

以下代码并行运行M1M2M3M4。每种方法都可能引发异常。该方法应返回四个异步方法的结果 - 方法返回的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"
c# asynchronous
4个回答
1
投票

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

您可能想看看它是否有故障:

myTask.Status == TaskStatus.Faulted

或者如果它已经例外:

if (myTask.Exception != null) 

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

See the docs here


0
投票

正如其他答案/评论所指出的,一种可能的方法是使用ContinueWithContinueWhenAll。这是一个聪明的把戏,因为TaskException属性:

获取导致Task过早结束的AggregateException。如果任务成功完成或尚未抛出任何异常,则返回null。

使用ContinueWith无论任务是否成功完成,它都将作为参数传递给委托函数。从那里你可以检查是否抛出异常。

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}";
}

0
投票

你可以将任务包裹在qazxsw poi中并抓住qazxsw poi(qazxsw poi),

WaitAll

0
投票

你能在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.
}

如果你想使用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);
© www.soinside.com 2019 - 2024. All rights reserved.