使用递归的异步/等待异常处理

3

请看以下代码:

void TopLevelCaller() {
    RecursiveAwaiter();
}

async Task RecursiveAwaiter() {
    var result = await ReceiveDataAsync();
    FireEvent(result);
    RecursiveAwaiter();
}

假设ReceiveDataAsync出现异常。是否可以修改代码以在TopLevelCaller()中捕获此异常,以便可以在TopLevelCaller()所在的类中完成所有错误处理?
最好让实现者像这样处理错误:
void TopLevelCaller() {
    try {
        RecursiveAwaiter();
    } catch (Exception e)
    {
        // Something went wrong. Handle appropriately.
    }
}

比如拥有以下内容:

async Task RecursiveAwaiter() {
    try {
        var result = await ReceiveDataAsync();
        FireEvent(result);
        RecursiveAwaiter();
    } catch (Exception e) {
        FireExceptionEvent(e);
    }
}

如果我没记错的话,async/await会抛出AggregateException。这样不就足够你所需要的了吗? - Tim
不要使用async avoid,它只适用于事件处理程序。为什么不使用await RecursiveAwaiter()呢?这将抛出异常。 - Panagiotis Kanavos
@Tim 不完全是这样。 实际上,它是 await 会抛出实际异常,或者如果抛出多个异常,则抛出 AggregateException - Panagiotis Kanavos
1
@PanagiotisKanavos async void 不仅适用于事件处理程序。在注释中警告可能是有益的,但是除了事件处理程序之外,还有其他有效的使用情况。而且,TopLevelCaller() 的名称强烈暗示了OP理解这一点,并且正确地使用了async void - user743382
1
@lejon void T() { R(); }async void T() { await R(); } 在处理来自 R 的异常方面有显著的差异,而您的问题特别涉及如何处理这些异常。 - user743382
显示剩余7条评论
1个回答

1
async void TopLevelCaller()

异步 void 几乎总是一个坏主意。它的设计是为了 WPF 控件事件。这是一种“发射并忘记”的功能,因此您将无法捕获顶级调用者抛出的异常。应该工作:

async Task TopLevelCaller() {
    try {
        await RecursiveAwaiter();
    } catch (Exception e)
    {
        // Something went wrong. Handle appropriately.
    }
}

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