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

如何避免在Task中使用try-catch处理CancellationToken取消逻辑?

优化C#取消逻辑,移除Task中的Try-Catch结构

针对你的场景,既然明确需要使用ManualResetEvent(这里推荐更轻量的ManualResetEventSlim),可以通过监听取消信号+等待句柄的方式彻底移除Task内的try-catch结构,同时让逻辑更清晰:

改进后代码示例

CancellationTokenSource? CancellationTS;
ManualResetEventSlim? CancelEvent;

void Bar() {
    CancellationTS?.Cancel();
}

void Foo() {
    CancellationTS = new CancellationTokenSource();
    CancelEvent = new ManualResetEventSlim(false);
    // 注册取消回调,当触发Cancel时立刻激活事件
    var cancelRegistration = CancellationTS.Token.Register(() => CancelEvent.Set());

    _ = Task.Run(() => {
        try {
            // 同时等待取消信号或15分钟超时
            var waitHandles = new[] { CancelEvent.WaitHandle };
            int waitResult = WaitHandle.WaitAny(waitHandles, TimeSpan.FromMinutes(15));

            bool isCancelled = waitResult == 0; // 返回0表示CancelEvent被触发
            if (isCancelled) {
                [...] // 取消后的业务逻辑
            } else {
                [...] // 超时后的业务逻辑
            }
        } finally {
            // 确保所有资源被正确释放,避免内存泄漏
            cancelRegistration.Dispose();
            CancelEvent.Dispose();
            CancellationTS.Dispose();
            CancellationTS = null;
            CancelEvent = null;
        }
    });
}

核心优化点

  • 移除try-catch:通过WaitHandle.WaitAny的返回值直接判断是取消还是超时,无需依赖捕获TaskCanceledException
  • 资源安全:使用finally块统一清理取消注册、事件句柄和CancellationTokenSource,避免资源泄漏
  • 适配远程触发场景:远程事件调用Bar()触发Cancel()时,注册的回调会立即激活CancelEvent,WaitAny会立刻返回并进入取消逻辑,响应速度不受影响
  • 更简洁的状态判断:直接通过waitResult的值区分取消和超时状态,逻辑一目了然

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 02:00:17