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

如何停止使用async/await的项目中后台运行的Worker Thread?

如何停止使用async/await的后台Worker Thread?

我在项目中使用了async和await,现在想要停止正在后台运行的Worker Thread,请问该如何实现?我尝试了以下代码:

private CancellationTokenSource cancellationToken;

private async void method1(int parameter) {
  //do something
}

private async Task method2(int parameter) {
  await Task.Run(() =>{
    method1(parameter);
    Task.Delay(1000).Wait();
  },
  cancellationToken.Token);
}

private async void bt_start_Click(object sender, EventArgs e) {
  cancellationToken = new CancellationTokenSource();
  await method2(123);
}

private async void bt_stop_Click(object sender, EventArgs e) {
  if (cancellationToken != null) {
    cancellationToken.Cancel();
  }
}

你的代码存在的问题

  1. method1是async void,无法跟踪执行状态,也无法响应取消请求
  2. Task.Run内部用Task.Delay(1000).Wait()同步阻塞线程,且全程未检查取消令牌,调用Cancel()后不会触发停止
  3. 取消令牌仅传给了Task.Run,但内部的异步/同步操作完全没感知到取消信号

正确实现方式

要实现可取消的异步任务,核心是让所有耗时操作都感知并响应CancellationToken,具体步骤如下:

1. 修正异步方法返回类型,传递取消令牌

除UI事件处理程序(必须用async void),其他异步方法都用async Task,并将CancellationToken传入需要响应取消的方法中。

2. 在操作中检查取消请求

在耗时循环或异步等待时,定期检查取消令牌:

  • 用token.ThrowIfCancellationRequested()主动抛出取消异常终止任务
  • 给支持取消的异步方法(比如Task.Delay)传入令牌,让异步操作本身响应取消

3. 处理取消异常

在启动任务的地方捕获OperationCanceledException,这是.NET中取消操作的标准异常。

修改后的完整代码示例

private CancellationTokenSource _cancellationTokenSource;

// 改为async Task,接受取消令牌
private async Task Method1(int parameter, CancellationToken token)
{
    // 模拟耗时业务逻辑,循环中定期检查取消
    while (true)
    {
        // 检查是否收到取消请求,若已取消则抛出异常终止任务
        token.ThrowIfCancellationRequested();
        
        // 执行你的业务操作
        // do something
        
        // 异步等待,避免阻塞线程,同时传入令牌响应取消
        await Task.Delay(100, token);
    }
}

private async Task Method2(int parameter, CancellationToken token)
{
    // 直接调用异步方法,无需额外用Task.Run(如果Method1本身是异步的)
    await Method1(parameter, token);
}

private async void BtStart_Click(object sender, EventArgs e)
{
    // 先终止之前可能在运行的任务
    _cancellationTokenSource?.Cancel();
    _cancellationTokenSource?.Dispose();
    
    // 创建新的取消令牌源
    _cancellationTokenSource = new CancellationTokenSource();
    
    try
    {
        await Method2(123, _cancellationTokenSource.Token);
    }
    catch (OperationCanceledException)
    {
        // 任务被取消时的处理逻辑,比如提示用户
        // MessageBox.Show("任务已停止");
    }
}

private void BtStop_Click(object sender, EventArgs e)
{
    // 触发取消请求
    _cancellationTokenSource?.Cancel();
    // 释放资源
    _cancellationTokenSource?.Dispose();
    _cancellationTokenSource = null;
}

特殊情况:如果Method1是同步耗时操作

如果Method1是纯同步的CPU密集型操作,需要用Task.Run放到后台线程,但同样要在内部检查取消令牌:

private async Task Method1(int parameter, CancellationToken token)
{
    await Task.Run(() =>
    {
        while (true)
        {
            token.ThrowIfCancellationRequested();
            
            // 执行同步耗时操作
            // do something
        }
    }, token);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 00:57:50