多核时代 .NET Framework 4 中的并行编程4---异常处理
任何程序都避免异常情况发生.那么如何在发生异常情况时,很好的处理掉异常,以便是我们的程序继续良好的运行呢?那么介绍几种处理.Net中并行编程处理异常的几种方式.
方法1: AggregateException
表示在应用程序执行期间发生的一个或多个错误.
当使用某个静态或实例任务类Task的Wait(),WaitAll(),WaitAny()方法和Result属性时,会传播异常,您可通过将调用包括在 try-catch 语句中来处理这些异常。 如果任务是所附加子任务的父级,或者您在等待多个任务,则可能会引发多个异常。 为了将所有异常传播回调用线程,任务基础结构会将这些异常包装在 AggregateException 实例中。 AggregateException 具有一个 InnerExceptions 属性,可枚举该属性来检查引发的所有原始异常,并单独处理(或不处理)每个异常。 即使只引发了一个异常,也仍会将该异常包装在 AggregateException 中。例子如下:
static void DealException()
{
Task task1 = new Task(() =>
{
throw new NotImplementedException("没有实现");
});
Task task2 = new Task(() =>
{
throw new ArgumentNullException("参数空");
});
Task task3 = new Task(() =>
{
throw new Exception("异常");
});
Task task4 = new Task(() =>
{
Console.WriteLine("正常");
});
task1.Start();
task2.Start();
task3.Start();
task4.Start();
try
{
Task.WaitAll(task1, task2, task3, task4);
}
catch (AggregateException agex)
{
foreach (var ex in agex.InnerExceptions)
{
Console.WriteLine("异常内容是:{0}", ex.Message);
}
});
}
通过代码,我们可以看到,我们只需要使用try{ …}catch()来捕获AggregateException异常,然后去处理其包含的异常即可.
方法2: AggregateException的Handle来处理每个异常.
AggregateException类型提供了一个Handle调用处理程序,以便我们对每个任务异常进行处理.代码如下:
static void DealException()
{
Task task1 = new Task(() =>
{
throw new NotImplementedException("没有实现");
});
Task task2 = new Task(() =>
{
throw new ArgumentNullException("参数空");
});
Task task3 = new Task(() =>
{
throw new Exception("异常");
});
Task task4 = new Task(() =>
{
Console.WriteLine("正常");
});
task1.Start();
task2.Start();
task3.Start();
task4.Start();
try
{
Task.WaitAll(task1, task2, task3, task4);
}
catch (AggregateException agex)
{
agex.Flatten().Handle((ex) =>
{
if (ex is NotImplementedException)
{
Console.WriteLine("忽略");
return true;
}
else
{
Console.WriteLine("异常内容是:{0},已处理", ex.Message);
return true;
}
});
}
Console.ReadLine();
}
上面代码中,捕获到异常,通过AggregateException异常实例的Flatten() 方法移除所有嵌套的 AggregateExceptions。处理程序返回true表示异常被处理。返回false则表示异常未被处理。
方法3:TaskScheduler.UnobservedTaskException 事件
当出错的 Task 的未观察到的异常将要触发异常升级策略时发生,默认情况下,这将终止进程。它提供了最后一种手段处理所有未处理异常。通过处理这个事件,就不用终止应用程序,而用你自己的异常处理逻辑替代它。代码如下:
TaskScheduler.UnobservedTaskException +=
(object sender, UnobservedTaskExceptionEventArgs eventArgs) =>
{
eventArgs.SetObserved();
eventArgs.Exception.Flatten().Handle(ex =>
{
Console.WriteLine("异常是:{0}", ex.Message);
return true;
});
};
Task task1 = new Task(() =>
{
throw new NullReferenceException();
});
Task task2 = new Task(() =>
{
throw new ArgumentOutOfRangeException();
});
task1.Start(); task2.Start();
while (!task1.IsCompleted || !task2.IsCompleted)
{
Thread.Sleep(500);
}
Console.ReadLine();
}
好,异常的处理介绍完毕。