重新使用稍加修改的代码from this answer,如何修改代码以实现@svick's advice:
但是如果将Task保存到变量并调用 task.Exception.Flatten(),将返回两个异常
?
//C# console app
class Program
{
static void Main(string[] args)
{
Test();
Console.ReadLine();
}
async static Task Test()
{
Task containingTask, nullRefTask, argTask;
try
{
containingTask = Task.Factory.StartNew
(() =>
{
nullRefTask = Task.Factory.StartNew(() =>
{
throw new NullReferenceException();
}
, TaskCreationOptions.AttachedToParent);
argTask = Task.Factory.StartNew(() =>
{
throw new ArgumentException();
}
, TaskCreationOptions.AttachedToParent);
}
);
await containingTask;
foreach(Exception ex in containingTask.Exception
.Flatten().InnerExceptions)
//Possible 'System.NullReferenceException'
{ //never entered
Console.WriteLine("@@@@@"+ex.GetType().Name);
}
}//try
catch (AggregateException ex)
{
Console.WriteLine("** {0} **", ex.GetType().Name);
foreach (var exc in ex.Flatten().InnerExceptions)
{
Console.WriteLine("$$$$$$"+exc.GetType().Name);
}
//foreach (Exception exxx in containingTask.Exception.Flatten().InnerExceptions)
//Use of unassigned local variable 'containingTask'
}
//foreach (Exception exxx in containingTask.Exception.Flatten().InnerExceptions)
////Use of unassigned local variable 'containingTask'
}
}
当我尝试使用或不使用try- / catch-blocks访问containingTask.Exception.Flatten().InnerExceptions
时,在try
- ,catch
- 块内或外,产生错误:
Use of unassigned local variable 'containingTask'
或
Possible 'System.NullReferenceException'
如何从两个子任务中查看/获取两个例外?
此部分已被删除,因为在纠正错字后,代码会产生预期结果
变体#2(C#控制台应用程序):
尝试从"Async - Handling multiple Exceptions"重现“变通方法”以查看所有子任务的所有异常:
class Program
{
static void Main(string[] args)
{
Tst();
Console.ReadLine();
}
async static Task Tst()
{
try
{
Task t= Task.Factory.StartNew
(
() =>
{
Task.Factory.StartNew
(
() =>
{ throw new NullReferenceException(); }
,TaskCreationOptions.AttachedToParent
);
Task.Factory.StartNew
(
() =>
{ throw new ArgumentException(); }
, TaskCreationOptions.AttachedToParent
);
}
);
await t.ContinueWith
(
tsk =>
{
if (tsk.Exception != null)
throw tsk.Exception;
}
);
}
catch (AggregateException ex)
{
foreach (var exc in ex.Flatten().InnerExceptions)
{
Console.WriteLine("** {0} **", exc.GetType().Name);
}
}
catch (Exception ex)
{
Console.WriteLine("## {0} ##", ex.GetType().Name);
}
}
}
答案 0 :(得分:4)
这与Task
或async
- await
无关。如果您将代码简化为以下代码,则仍会出现相同的错误:
string s;
try
{
s = "something";
}
catch (SomeException)
{
}
Console.WriteLine(s);
编译器假定try
内部可能会抛出异常,但在执行赋值之前会出现此错误。为什么编译器会假设?因为它实际上可能发生:ThreadAbortException
几乎可以抛出任何一点。关于明确赋值的规则并不会过于聪明,无法知道可以抛出特定异常的规则是什么。
要解决此问题,请为变量指定null
(或其他默认值)。