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

如何为WPF中带进度报告的异步耗时任务添加取消令牌?

在WPF异步任务中添加取消令牌的实现方案

没问题,我来帮你给这个带进度报告的WPF异步任务加上取消功能,咱们一步步来实现:

1. 先声明取消令牌源字段

首先在你的页面类里定义一个CancellationTokenSource的成员变量,因为咱们需要在开始按钮和可能的取消按钮中共享它:

private CancellationTokenSource _cts;

2. 修改开始按钮的点击事件

更新btnStart_Click方法,初始化取消令牌源,异步执行耗时操作,同时处理取消异常和按钮状态:

private async void btnStart_Click(object sender, RoutedEventArgs e)
{
    // 如果已有任务在运行,直接返回避免重复执行
    if (_cts != null) return;

    txt_importStatus.Text = "";
    btnStart.IsEnabled = false; // 禁用开始按钮防止重复点击
    _cts = new CancellationTokenSource();

    try
    {
        var progress = new Progress<string>(progress_info =>
        {
            txt_importStatus.Text = progress_info + Environment.NewLine + "系统处理Excel文件内容期间请不要关闭此窗口";
        });

        // 异步执行耗时操作,传入进度回调和取消令牌
        await Task.Run(() => DoProcessing(progress, _cts.Token), _cts.Token);

        txt_importStatus.Text += Environment.NewLine + "处理完成!";
    }
    catch (OperationCanceledException)
    {
        txt_importStatus.Text += Environment.NewLine + "任务已被用户取消!";
    }
    catch (Exception ex)
    {
        txt_importStatus.Text += Environment.NewLine + $"处理出错:{ex.Message}";
    }
    finally
    {
        // 释放资源并重置状态
        _cts.Dispose();
        _cts = null;
        btnStart.IsEnabled = true; // 恢复开始按钮可用状态
    }
}

3. 更新耗时操作方法,支持取消

修改DoProcessing方法,让它接受CancellationToken,并在关键步骤检查取消请求:

private void DoProcessing(IProgress<string> progress, CancellationToken token)
{
    // 这里替换成你实际的Excel处理逻辑
    // 模拟遍历Excel数据的耗时操作
    for (int i = 0; i < 100; i++)
    {
        // 每次执行前检查是否收到取消请求,如果有则抛出异常终止任务
        token.ThrowIfCancellationRequested();

        // 模拟耗时工作(比如读取Excel行、处理数据)
        Thread.Sleep(100);

        // 向UI报告当前进度
        progress.Report($"已处理 {i+1}/100 条数据");
    }
}

4. 可选:添加取消按钮

如果需要给用户手动取消的入口,可以加一个取消按钮,点击时触发取消:

private void btnCancel_Click(object sender, RoutedEventArgs e)
{
    // 安全触发取消请求
    _cts?.Cancel();
}

关键注意点

  • 资源释放:CancellationTokenSource实现了IDisposable,必须在任务结束后调用Dispose()避免资源泄漏
  • 线程安全:Progress<T>内部会自动把回调切换到UI线程,所以不用手动调用Dispatcher.Invoke
  • 任务状态控制:禁用开始按钮能防止用户重复触发任务,提升体验
  • 取消时机:在耗时操作的循环或关键步骤中调用token.ThrowIfCancellationRequested(),确保任务能及时响应取消请求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:37:53