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

如何对未被等待的任务执行try/catch/finally清理操作?

如何对未被等待的任务执行try/catch/finally清理操作?

咱们先看你这段代码的问题:你启动了readTask和writeTask两个后台任务,但如果后面的DoSomeNonAsyncWork或者MaybeSomeOtherAsyncWork抛出异常,这两个子任务可能还在后台瞎跑,不仅浪费资源,在旧版.NET里甚至会因为未观察到的异常搞崩程序。

要解决这个问题,核心就是主流程出问题时,先通知子任务停止,再等待它们完成,最后统一处理异常和清理资源。我给你调整后的代码如下:

public async Task Handle(HttpContext httpContext, WebSocket socket) 
{      
    using var cts = CancellationTokenSource.CreateLinkedTokenSource(httpContext.RequestAborted);
    Task readTask = null;
    Task writeTask = null;
    try 
    {
        readTask = Run(socket, cts.Token);
        writeTask = Run2(socket, cts.Token);

        DoSomeNonAsyncWork(cts.Token); // 同步方法抛异常会直接进catch
        await MaybeSomeOtherAsyncWork(cts.Token); // 异步方法抛异常也会进catch

        // 主流程正常走完,等待子任务全部完成
        await Task.WhenAll(readTask, writeTask);
    }
    catch (Exception mainEx)
    {
        // 主流程出问题了,先给子任务发取消信号
        cts.Cancel();

        // 必须等待子任务结束,不然会留下未观察异常的隐患
        if (readTask != null && writeTask != null)
        {
            try
            {
                await Task.WhenAll(readTask, writeTask);
            }
            catch (Exception taskEx)
            {
                // 这里处理子任务抛出的异常,比如打日志或者合并到主异常里
                Console.WriteLine($"子任务执行异常:{taskEx.Message}");
            }
        }

        // 把主流程的异常抛出去,或者在这里统一做业务处理
        throw new InvalidOperationException("主流程执行失败", mainEx);
    }
    finally
    {
        // 兜底的资源清理,确保WebSocket被正确关闭
        if (socket.State == WebSocketState.Open || socket.State == WebSocketState.CloseSent)
        {
            await socket.CloseAsync(
                WebSocketCloseStatus.NormalClosure, 
                "操作结束,资源已清理", 
                CancellationToken.None);
        }
    }
}

再给你划几个必须注意的点:

  • 别让子任务“失控”:只要启动了任务,哪怕没立刻await,也要在异常发生时主动取消并等待完成,不然资源泄漏和未观察异常的坑迟早要踩
  • CancelToken要串到底:你已经把cts和httpContext.RequestAborted关联了,这样客户端取消请求时子任务也会收到信号,这一点做得不错,要保持
  • finally做最后兜底:不管主流程是正常完成还是异常退出,finally块的清理逻辑都会执行,比如关闭WebSocket,这是避免资源泄漏的关键
  • 异常分层处理:主流程和子任务的异常可以分开处理,也可以合并成一个异常抛出,完全看你的业务需求

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 13:29:40