如何在BackgroundWorker.RunWorkerCompleted事件处理程序中区分不同的异常类型

4

我正在使用C#进行一个小型的爱好项目,但我并不精通这门语言,遇到了以下问题:

假设你使用BackgroundWorker实现异步操作。如果出现异常,则会引发RunWorkerCompleted事件,而RunWorkerCompletedEventArgs.Error将不为null。

那么下面的方式是否是处理不同异常类型的规范方式?(这里所有异常都是继承关系下的同级)

if (e.Error != null)
{
    FirstKindOfException e1 = e as OneKindOfException;
    SecondKindOfException e2 = e as SecondKindOfException;
    ...
    LastKindOfException en = e as LastKindOfException;
    if (e1 != null)
    {
        ...
    }
    else if (e2 != null)
    {
        ...
    }
    ...
    else
    {
        ...
    }
}

它能运行,但是...感觉不是很

4个回答

7
您可以使用is来保持每个测试的紧密范围:
if (e.Error is FirstKindOfException )
{
    ...
}
else if (e.Error is SecondKindOfException)
{
    ...
}

(如果需要异常中的特殊值,可以重新抛出异常)

说实话,我很少需要处理许多不同类型的异常。在大多数情况下,只需恢复(补偿)到已知状态并适当地报告错误即可。通常我更喜欢在开始操作之前测试可能出现的错误,这样异常才是真正的异常情况。


没错,但是在代码中 e1 和 e2 都应该是 e.Error。如果您不同意,请回滚。 - H H
@Henk,实际上我只想打“e”,但你是对的——它写错了。 - Marc Gravell

5

使用is运算符:

if (e.Error is FirstKindOfException) {
   //...
}
else if (e.Error is SecondKindOfException) {
   //...
}
//etc..

如果你不知道如何处理这些异常,那就简单粗暴地截断它。如果你知道如何处理,你应该在DoWork()事件处理程序中捕获它们,一旦状态消失后再试图处理它们是没有意义的:

if (e.Error != null) throw new BackgroundTaskFailedException(e.Error);

3
@Aliostad: 关键是不要捕获你不知道如何处理的异常。性能确实无关紧要,程序会慢几毫秒崩溃。如果异常是可恢复的,则应该在DoWork()中进行处理。 - Hans Passant
他想处理并防止崩溃,这就是为什么他在检查它。我同意他必须在客户端处理,而不是在BackgroundWorker本身处理,但最终,通常没有区分的必要。 - Aliostad
1
顺便说一下,恭喜你达到了10万的里程碑! - Aliostad

2

也许可以使用 is 运算符?

if (e is OneKindOfException)
{
}
else if (e is SecondKindOfException)
{
}

1

是的,你可以这样做,但实际上取决于你要如何处理所有这些异常类型。通常这只会显示给用户,所以没有必要检查错误的类型。

此外,你需要记住,异常的类型很可能是AggregateException - 这是从Task<T>操作返回的 - 所以你需要小心。


从未听说过AggregateException。如果我只使用BackgroundWorker而不是Task<T>,我应该担心吗? - Laurynas Biveinis
如果您使用Task<T>,那么您总是会得到AggregateException(其中包含其余的异常)。我不确定BackgroundWorker是否也是如此。但是如果您没有收到它,那么就没问题了,不用担心。 - Aliostad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接