以下代码并行运行M1
,M2
,M3
,M4
。每种方法都可能引发异常。该方法应返回四个异步方法的结果-方法返回的int或Exceptions。
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"
答案 0 :(得分:1)
每个任务都有一个Status和and Exception属性。
您可能想看看它是否有故障:
myTask.Status == TaskStatus.Faulted
或者,如果除外:
if (myTask.Exception != null)
您可以使用ContinueWhenAll
运行所有任务,然后检查状态。
答案 1 :(得分:0)
您是否可以将每个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
,可以使用await
并忽略异常,然后执行与上述相同的操作来检索单个任务结果...
try { await Task.WhenAll(t1, t2, t3); } catch { };
// ^^^^^^^^^
// then same as ^ above
答案 2 :(得分:0)
正如其他答案/评论所指出的那样,一种可能的方法是使用ContinueWith
或ContinueWhenAll
。这是一个巧妙的技巧,因为Task
具有Exception
属性:
获取导致任务提前结束的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}";
}
答案 3 :(得分:0)
您可以将任务包装在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.
}