我的理解是当一个Task抛出异常时,当观察到Tasks的(Result,WaitAll)属性或GC发生时,它会被存储并重新抛出.鉴于此,我运行以下代码.
Task t = Task.Factory.StartNew(() =>
{
throw new Exception("Hello World");
});
for (int i = 0; i < 10000; i++)
{
Console.WriteLine(i);
}
GC.Collect();
for (int a = 20; a < 30; a++)
{
Console.WriteLine(a);
}
Run Code Online (Sandbox Code Playgroud)
但是当我运行上面的代码时,我除了在GC.Collect上抛出一个异常但它没有发生,而是继续从第二个循环打印输出.我的理解在哪里错了?
在您的示例代码中,Task对象t仍在范围内,因此在您调用时不符合收集条件GC.Collect().
除此之外,.NET 4.0和.NET 4.5之间的行为也发生了变化:
在.NET 4.0中,未观察到的异常将在终结器线程上引发异常,从而导致进程崩溃.
在.NET 4.5中,此行为已更改,因此默认情况下将忽略未观察到的异常.您可以设置一个配置开关来重新打开旧的严格行为.
因为使用 Task 就像使用 Thread 一样,它是单独执行的(除了主线程之外)。因此,通过这种方式,您可以获得循环输出以及执行的GC.Collect,直到异常行被任务执行为止。