You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Task.Run()中的异常传递至主线程以实现全局处理?

问题描述

我正尝试实现一个通用方法来异步处理所有API调用并处理异常。如何将Task.Run()内部的异常传递到主线程,以便在未处理异常中进行全局处理?

我的全局异常处理器如下:

AppDomain.CurrentDomain.UnhandledException += LogUnhandledCurrentDomainException;
Dispatcher.UnhandledException += OnDispatcherUnhandledException;

异步API调用的通用方法:

public async Task<T> InvokeApiAsync<T>(Func<T> function)
{
    return await Task.Run(function);
}

我通过WPF视图模型中的方法调用该异步函数:

private async Task LoadDocuments()
{
    IsBusy = true;
    Documents = await _serviceInvoker.InvokeApiAsync(() => _blobService.GetBlobs().ToList());
    IsBusy = false;
}

上述方法是从Caliburn.Micro的事件中调用的:

protected override async Task OnInitializeAsync(CancellationToken cancellationToken)
{
    await LoadDocuments();            
    await base.OnInitializeAsync(cancellationToken);
}
解决方案

1. 补充TaskScheduler.UnobservedTaskException事件监听

你的代码中,await Task.Run(function)已经会将内部异常重新抛回主线程的调用上下文,但**async Task方法的未处理异常不会触发AppDomain.CurrentDomain.UnhandledException**,而是会触发TaskScheduler.UnobservedTaskException事件。需要添加这个事件的处理器来捕获这类异常:

TaskScheduler.UnobservedTaskException += LogUnobservedTaskException;

// 对应的处理器示例
private void LogUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
    // 展开嵌套异常并记录日志
    var targetException = e.Exception.Flatten();
    // 标记异常为已观察(可选,避免应用因未处理任务异常崩溃)
    e.SetObserved();
}

2. 修复LoadDocuments的状态重置逻辑

当前代码中,如果API调用抛出异常,IsBusy = false不会执行,导致UI一直处于忙碌状态。建议用try/finally块确保状态重置:

private async Task LoadDocuments()
{
    IsBusy = true;
    try
    {
        Documents = await _serviceInvoker.InvokeApiAsync(() => _blobService.GetBlobs().ToList());
    }
    finally
    {
        IsBusy = false;
    }
}

3. 关于Caliburn.Micro的异步方法处理

Caliburn.Micro会正确处理OnInitializeAsync这类异步生命周期方法的返回任务,但如果该方法抛出异常,框架不会自动将其冒泡到全局异常处理器。此时未处理的异常会被包装到Task中,最终触发TaskScheduler.UnobservedTaskException事件,通过步骤1添加的处理器即可捕获。

内容的提问来源于stack exchange,提问作者Vinay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 20:34:54