尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

Task异步练习(进度条)

Task异步练习(进度条)
📅 发布时间:2026/7/8 2:18:59

WinForm窗体设计:

代码:

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace 进度条 { public partial class Form1 : Form { private CancellationTokenSource _cts;//通行证 private bool _isPause=false;//暂停标记 private bool _isRunning=false;//运动标记 private int _currentNum = 0;//值 public Form1() { InitializeComponent(); progressBar1.Minimum = 0;//设置最小进度条 progressBar1.Maximum = 100;//设置最大进度条 progressBar1.Value = 0;//进度初始值 dataGridView1.Columns.Add("colNum", "数字");//在表格中添加列(列名,显示在表格中列名) dataGridView1.Columns.Add("colVal", "值"); } private async Task RunLoopAsync(CancellationToken token)//从开启按钮传递过来的通行证,用来监听取消信号 { await Task.Run(async () => { for (; _currentNum <= 100; _currentNum++) { token.ThrowIfCancellationRequested(); // 暂停阻塞逻辑 while (_isPause) { await Task.Delay(1000, token); } int val = _currentNum * 10; // 后台子线程必须Invoke切UI线程更新控件 this.Invoke(new Action(() => { progressBar1.Value = _currentNum; label1.Text = $"当前进度:{_currentNum}/100,数字值:{val}"; dataGridView1.Rows.Add(_currentNum, val); })); await Task.Delay(500, token); } // for循环执行完毕,全部数字跑完 this.Invoke(new Action(() => { label1.Text = "全部执行完毕!"; MessageBox.Show("循环数字已到达100,任务自动结束!"); })); _currentNum = 0; this.Invoke(new Action(() => { progressBar1.Value = 0; })); }, token); // Task.Run 闭合 + 传入取消令牌 } private void btnPause_Click(object sender, EventArgs e) { if (!_isRunning) return; _isPause = true; label1.Text += "【已暂停】"; } private void btnContinue_Click(object sender, EventArgs e) { if(!_isRunning||!_isPause) return; _isPause=false; } private void btnCancel_Click(object sender, EventArgs e) { if(!_isRunning) return; _cts?.Cancel(); label1.Text = null; dataGridView1.Rows.Clear(); progressBar1.Value = 0; _currentNum = 0; } private async void btnStart_Click(object sender, EventArgs e) { if (_isRunning) { MessageBox.Show("任务正在运行,请勿重复开启!"); return; } _isRunning = true; _isPause = false; _cts = new CancellationTokenSource(); CancellationToken token = _cts.Token; try { await RunLoopAsync(token); } catch (OperationCanceledException) { label1.Text = "任务已取消"; } catch (Exception ex) { MessageBox.Show($"运行异常:{ex.Message}"); } finally { _isRunning = false; _cts?.Dispose(); _cts = null; } } } }

WinForm 异步后台进度条【暂停、继续、取消、断点续跑】终极知识总结

一、整体功能(你当前代码实现)

  1. 点击开启:后台线程循环 0~100,每 500ms 刷新进度条、Label、DataGridView
  2. 支持暂停 / 继续(软暂停,不销毁任务、可续跑)
  3. 支持取消(硬终止任务、清空界面)
  4. 防止重复开启多任务
  5. 断点续跑:暂停 / 取消后再次开启从上次数字继续
  6. 自带异常捕获、资源释放、线程安全、UI 不卡顿

二、全局变量 4 个(必考)

csharp

运行

private CancellationTokenSource _cts; // 任务取消器(发停止信号) private bool _isPause = false; // 暂停标记 private bool _isRunning = false; // 任务运行锁(防重复启动) private int _currentNum = 0; // 全局记录当前循环数字(实现断点续跑)

作用一句话

  1. _cts:负责取消任务
  2. _isPause:负责暂停 / 继续
  3. _isRunning:负责防止多开
  4. _currentNum:负责断点续跑

三、窗体构造函数知识点

csharp

运行

progressBar1.Minimum = 0; progressBar1.Maximum = 100; progressBar1.Value = 0; dataGridView1.Columns.Add("colNum", "数字"); dataGridView1.Columns.Add("colVal", "值");
  1. 进度条范围0~100和循环完全对齐
  2. 代码动态创建表格两列,无需手动设计

四、核心重点:为什么你的代码是真正后台线程?

关键区别(你之前最大的疑惑)

1.async / await不会开后台线程

2.Task.Run才会开后台线程

你现在正确代码:

csharp

运行

await Task.Run(async () => { // 这里 100% 后台子线程!! });

所以:

  • 循环、计算、Delay全部跑在线程池后台
  • 不卡 UI
  • 必须 Invoke 更新控件(否则报错跨线程)

五、核心方法 RunLoopAsync 逐知识点

1. 方法标准规范

csharp

运行

private async Task RunLoopAsync(CancellationToken token)
  • 自定义异步方法必须返回Task(不能 async void)
  • token:接收取消信号,用来随时终止循环

2. 断点续跑 for 循环(高频考点)

csharp

运行

for (; _currentNum <= 100; _currentNum++)
  • 没有初始化语句
  • 循环变量用全局字段
  • 暂停、取消后数字不会丢 →实现断点续跑

3. 任务取消检测

csharp

运行

token.ThrowIfCancellationRequested();
  • 检测是否点击了取消
  • 点击取消直接抛异常 → 终止后台任务

4. 软暂停逻辑(重点)

csharp

运行

while (_isPause) { await Task.Delay(1000, token); }
  • 不销毁任务、不退出循环
  • 原地无限等待 →暂停
  • 改_isPause=false→立刻继续

5. Invoke 跨线程更新 UI(必考)

csharp

运行

this.Invoke(new Action(() => { progressBar1.Value = _currentNum; label1.Text = $"当前进度:{_currentNum}/100,数字值:{val}"; dataGridView1.Rows.Add(_currentNum, val); }));

为什么必须 Invoke?

  • 循环代码在后台子线程
  • WinForm 控件只能由 UI 主线程访问
  • 子线程改控件 = 报错
  • Invoke:把子线程代码切回 UI 主线程执行

6. 异步延时

csharp

运行

await Task.Delay(500, token);
  • 不阻塞线程、不卡界面
  • 带 token:取消时立刻中断等待

六、任务跑完收尾逻辑

csharp

运行

this.Invoke(new Action(() => { label1.Text = "全部执行完毕!"; MessageBox.Show("循环数字已到达100,任务自动结束!"); })); _currentNum = 0;
  • 跑完归零,下次从头开始

七、四个按钮逻辑总结(超级清晰)

1. 开启按钮(核心入口)

  • 判断_isRunning防止重复开启
  • 创建_cts取消源
  • 传递 token 给后台任务
  • try-catch捕获取消异常、程序异常
  • finally 必执行:释放资源、解锁任务状态

2. 暂停按钮

csharp

运行

_isPause = true;

后台while进入死循环等待 → 暂停

3. 继续按钮

csharp

运行

_isPause = false;

退出 while 循环 → 继续跑

4. 取消按钮

csharp

运行

_cts.Cancel();
  • 给后台发终止信号
  • 清空表格、进度条、数字

八、三大核心机制区别(考试必考)

1. 后台线程机制

Task.Run→ 真正后台运行,UI 不卡、必须 Invoke

2. 暂停机制(软暂停)

布尔变量控制,任务不销毁、线程不退出、可续跑

3. 取消机制(硬终止)

CancellationTokenSource→ 强制终止任务,抛取消异常


九、异常处理机制

  1. OperationCanceledException用户手动取消任务 →正常预期操作
  2. 通用 Exception 程序 Bug、计算错误、控件错误 →兜底保护程序不崩溃

十、资源释放(重要)

csharp

运行

finally { _isRunning = false; _cts?.Dispose(); _cts = null; }
  • 无论成功、报错、取消一定执行
  • 释放取消令牌资源,防止内存泄漏

十一、你代码的完美架构总结(背诵版)

  1. Task.Run开启后台线程 → UI 永不卡死
  2. 全局变量记录状态→ 实现暂停、继续、续跑、防多开
  3. token 令牌→ 安全取消任务
  4. Invoke→ 解决跨线程 UI 报错
  5. async/await→ 优雅异步,不阻塞
  6. try-catch-finally→ 安全稳定、资源不泄漏

十二、最终一句话超级总结

  • Task.Run 负责后台运行
  • while (_isPause) 负责暂停
  • CancellationToken 负责取消
  • 全局变量负责续跑、防多开
  • Invoke 负责跨线程更新 UI
  • async/await 负责不卡界面

相关新闻

  • 团建研学活动文创礼品怎么选?景德镇陶瓷配套产品场景采购指南
  • 松下 A5/A6 伺服驱动器 X4 接口接线实战:位置模式 8 个关键引脚与 PLC 连接详解
  • PayPal Ventures关停:60亿基金因战略调整落幕,被投企业何去何从?

最新新闻

  • Memcached 1.6.44 发布:安全修复版本,解决多项问题!
  • Anthropic开源J-Lens:读出Claude“内心想法”,揭示其类似人类意识的结构
  • AI智能体大规模上岗倒计时!2026年这些岗位将遭“取代”,哪些人将迎来黄金时代?
  • 餐饮品牌策划设计公司怎么选?看看东莞这家做了18年的老牌机构
  • 用了这个AI方案,我敢让娃自己安排暑假(小学初中暑期AI学习方案推荐)
  • AI多Agent协作系统实战(八):UI一致性与自动化流水线的连环坑

日新闻

  • PROPKA 3深度解析:蛋白质pKa预测的实战指南与算法原理
  • 微信小程序 globalData 监听:基于 Object.defineProperty 的 3 种实现方案对比
  • MySQL 8.0 数据清洗实战:3类异常值识别与 UPDATE/DELETE 批量处理

周新闻

  • 基于YOLOv12的番茄成熟度智能检测系统开发
  • 终极RimWorld模组管理指南:用RimSort告别模组冲突烦恼
  • AI Agent框架开发:从理论到实践的完整指南

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号