这是我的代码:
private static Stopwatch _stopwatch;
static void PrintException(Exception ex)
{
Console.WriteLine(_stopwatch.Elapsed);
Console.WriteLine(ex);
}
static void ThrowException1()
{
throw new InvalidAsynchronousStateException();
}
static void ThrowException2()
{
throw new NullReferenceException();
}
static async Task ExecuteTask1()
{
await Task.Delay(1000);
ThrowException1();
}
static async Task ExecuteTask2()
{
await Task.Delay(2000);
ThrowException2();
}
static async Task Execute()
{
var t1 = ExecuteTask1();
var t2 = ExecuteTask2();
try
{
await t2;
}
catch (NullReferenceException ex)
{
// the NullReferenceException will be captured
Console.WriteLine("==============");
PrintException(ex);
}
}
static void Main(string[] args)
{
TaskScheduler.UnobservedTaskException += (sender, ev) => PrintException(ev.Exception);
_stopwatch = Stopwatch.StartNew();
Execute();
while (true)
{
Thread.Sleep(5000);
GC.Collect();
}
}
实际上,我没有在t1
方法中等待Execute
,但它似乎仍在执行,因为我在大约五秒后捕获了AggregateException
。
t1执行时有人可以告诉我吗?在我的情况下,打印到控制台的例外订单是1. NullReferenceException
2. AggregateException
答案 0 :(得分:9)
在async / await世界中,任务“热”。因此,当您致电ExecuteTask1
时,已经处理了返回给您的任务。它已经开始了。您可以在Console.WriteLine
的开头添加ExecuteTask*
,以确保它们立即开始。
await
仅用于(异步)等待任务的完成。它不会启动任务。
我的博客上有async
intro,您可能会觉得有帮助。
答案 1 :(得分:2)
如果你没有await
任务它仍然会执行,那么你当前的执行环境就不会#34;为它而烦恼"。
这意味着你无法直接控制任务,如果出现问题"在任务内部#34;异常不会像使用await
或t1.Wait()
时那样直接传播到执行上下文。
一般而言,在AggregateException
内部装入任务中的异常,因此您无法执行以下操作:
catch (NullReferenceException ex)
您需要做类似的事情并检查,例如对于内部异常:
catch (AggregateException ex)
{
if(ex.InnerException is NullReferenceException)
// handle NRE
else
throw; // NOT "throw ex" to keep the stack trace
}
答案 2 :(得分:2)
任务是在您调用ExecuteTask1的位置执行的:
var t1 = ExecuteTask1();
你不需要等待任务执行它,无论如何都会运行...如果你希望你的代码只在任务完成后才能继续执行,你等待任务,否则你的代码将继续运行任务开始运行后立即执行而不等待任务完成。