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

