如何避免在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
相关产品推荐
相关产品推荐

