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

如何不使用类全局CancellationTokenSource实现带超时的单事件等待?

问题描述

我当前的实现依赖类全局的CancellationTokenSource来实现带超时的单事件等待功能,请问能不能不借助全局的CancellationTokenSource达成同样的效果?

现有代码如下:

CancellationTokenSource _waitCTS = null;

private async Task WaitWithTimeout(string param)
{
    _waitCTS?.Dispose();
    _waitCTS = new CancellationTokenSource();

    XClass x = new XClass(param);
    x.OnReceived += X_OnReceived;

    try
    {
        await Task.Delay(5000, _waitCTS.Token).ConfigureAwait(true);
    }
    catch (TaskCanceledException)
    {
        Debug.WriteLine("Timed out");
    }

    x.OnReceived -= X_OnReceived;
    x.Cleanup();
}

private void X_OnReceived(object sender, SelectedItemEventArgs e)
{
    Debug.WriteLine(e.ReceivedItem);
    if (_waitCTS != null)
        _waitCTS.Cancel();
}
解决方案

当然可以,用TaskCompletionSource<T>就能替代全局CancellationTokenSource,把等待逻辑和事件回调封装在方法内部,彻底摆脱全局状态的依赖。

改造后的代码示例:

private async Task WaitWithTimeout(string param)
{
    using var tcs = new TaskCompletionSource<bool>();
    XClass x = new XClass(param);
    
    // 定义局部事件回调,直接访问当前方法内的tcs
    void OnReceivedHandler(object sender, SelectedItemEventArgs e)
    {
        Debug.WriteLine(e.ReceivedItem);
        tcs.TrySetResult(true);
    }

    x.OnReceived += OnReceivedHandler;

    try
    {
        // 同时等待事件触发和超时,哪个先完成就执行对应逻辑
        var completedTask = await Task.WhenAny(tcs.Task, Task.Delay(5000)).ConfigureAwait(true);
        if (completedTask != tcs.Task)
        {
            Debug.WriteLine("Timed out");
        }
    }
    finally
    {
        // 无论结果如何,都要解绑事件并清理资源
        x.OnReceived -= OnReceivedHandler;
        x.Cleanup();
    }
}

核心改动说明

  • 去掉全局变量:用局部的TaskCompletionSource<bool>替代全局CancellationTokenSource,事件触发时通过TrySetResult标记任务完成,不需要取消操作。
  • 局部回调绑定:把事件回调定义为方法内部的局部委托,直接访问当前方法的tcs,避免依赖外部状态。
  • 更简洁的等待逻辑:用Task.WhenAny同时监听事件完成和超时任务,无需捕获异常来判断超时,代码更直观。
  • 可靠的资源清理:用finally块确保事件解绑和资源清理,不管是事件触发还是超时,都会执行这部分逻辑,比原写法更稳妥。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 13:55:17