笔记承接承接Thread线程、线程信号案例Task是.NET高阶异步封装基于线程池封装相比原生Thread用法更简单、自带状态监控、自带取消机制是目前主流异步写法全文清理冗余代码、修复模糊注释、拆分多层泛型任务适配课堂考试窗体控件Label标签、button1(启动任务)、button2(取消任务)一、精简引用命名空间剔除全部无效冗余引用保留运行必备依赖标注每一项作用//基础系统命名空间 using System; //✅Task异步任务专属命名空间 using System.Threading.Tasks; //✅线程、取消令牌依赖 using System.Threading; //✅WinForm窗体控件 using System.Windows.Forms;二、全局变量释义全局声明任务对象、取消通行证实现启停、取消复用逐句拆解namespace _4Task基础 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } //1.声明异步任务对象管控异步任务状态、启动、执行 Task t1 null; //2.异步任务取消令牌源俗称【取消通行证】 //作用安全终止Task异步任务禁止暴力销毁线程官方推荐取消方案 CancellationTokenSource cts new CancellationTokenSource(); //计数变量页面自增数字 int i 0;三、Task三大创建方式考试必考原代码大量冗余注释、重复示例拆分整理三种创建方式优先级从低→高按课堂掌握权重排序3.1 方式一new Task() 实例化创建手动启动特点手动new创建必须调用.Start()才会执行任务灵活性最高可以绑定取消令牌3.1.1 基础无参写法//完整版传递Action委托 t1 new Task(new Action(() { })); //语法糖简化写法常用 t1 new Task(() { }); //绑定外部方法课堂重点、项目常用 t1 new Task(DoWork);3.1.2 带参数任务//第二个参数传入异步任务实参 t1 new Task((obj) { Console.WriteLine(obj); },hello);3.1.3 绑定取消令牌本案例核心//cts.Token传递取消通行证 //给异步任务绑定取消权限后续可以通过cts.Cancel()终止任务 t1 new Task(DoWork, cts.Token);3.2 方式二Task.Run() 静态创建自动执行特点调用方法直接自动启动任务无需手动Start代码最简开发最常用分为无返回值、有返回值、嵌套任务3.2.1 无返回值委托//绑定外部方法最简写法必须掌握 Task.Run(F1);3.2.2 基础返回值委托 FuncAction无返回值委托 | Func有返回值委托//返回字符串 Task.Run(new Funcstring(() { return 11; })); //返回整型 Task.Run(new Funcint(() 100));3.2.3 嵌套Task返回值难点任务返回值依旧是Task形成异步嵌套多用于链式异步调用//返回值为Task的异步任务 Task.Run(new FuncTask(() { return new Task(() { }); } ));3.3 方式三Task.Factory 任务工厂创建特点底层原生创建方式适配复杂调度写法繁琐课堂了解即可//无返回值 Task.Factory.StartNew(() {}); //带返回值 Task.Factory.StartNew(() gt;{ return 100; });四、泛型Task多层返回值拆解通俗易懂原代码多层嵌套晦涩难懂分层通俗解释解决看不懂嵌套问题Taskint普通泛型任务任务执行完毕返回数字100Taskstring任务执行完毕返回字符串11TaskTask外层任务执行完毕返回一个新的空任务TaskTaskint外层任务执行完毕返回一个带整型返回值的任务TaskTaskTask三层嵌套外层返回二级任务二级再返回三级任务工程极少使用仅语法演示五、业务方法拆分5.1 F1返回值测试方法/// summary /// 有返回值异步回调方法匹配Func委托 /// /summary public string F1() { Console.WriteLine(F1); return 哈兰德; }5.2 DoWork 主业务方法UI自增核心依靠取消令牌状态实现循环启停安全终止异步修复原代码注释歧义/// summary /// 异步主任务页面数字自增刷新label /// 依靠 cts.IsCancellationRequested 判断是否取消任务 /// /summary public void DoWork() { Console.WriteLine(dowork); //IsCancellationRequested取消请求标记 //false未收到取消指令任务继续执行 //true收到取消指令终止循环、停止任务 while (!cts.IsCancellationRequested) { //跨线程刷新UITask属于子线程禁止直接操作控件 Invoke(new Action(() { label1.Text i.ToString(); })); i; } }六、按钮事件逐行拆解6.1 button1启动异步任务重点任务完成必须重建取消令牌一个任务对应一个通行证复用令牌会报错private void button1_Click(object sender, EventArgs e) { //Task三大状态属性考试必背 t1.IsCanceled; //任务是否【主动取消】结束 t1.IsCompleted; //任务是否执行完毕正常结束/取消/异常都算完成 t1.IsFaulted; //任务是否报错、异常终止 //判定任务执行完成后重置令牌、重建任务 if (t1.IsCompleted) { cts new CancellationTokenSource();//新建取消通行证 t1 new Task(DoWork, cts.Token);//绑定全新通行证 } t1.Start();//手动启动异步任务 }6.2 button2取消异步任务private void button2_Click(object sender, EventArgs e) { //发送取消指令IsCancellationRequested 自动变为true //触发do-while循环退出安全停止任务 cts.Cancel(); }、核心重难点总结7.1 Task和Thread区别面试简答Thread原生线程粒度底层需要手动管控生命周期无自带取消、状态属性Task基于线程池封装上层异步封装自带完成、异常、取消状态语法简洁7.2 取消令牌规则CancellationTokenSource取消通行证管理器cts.Token通行证绑定Task任务禁止复用旧通行证每次新建Task必须重新new CancellationTokenSource7.3 Task三种创建对比new Task手动启动支持绑定取消令牌可控性最强Task.Run自动执行写法最简开发首选Task.Factory底层工厂复杂调度使用7.4 三大状态属性IsCompleted只要任务停止正常、报错、取消全部为trueIsCanceled只有主动调用Cancel取消任务才为trueIsFaulted代码报错、抛出异常任务中断为true八、整理精简可直接运行完整版代码using System; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace _4Task基础 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } Task t1 null; //异步取消通行证 CancellationTokenSource cts new CancellationTokenSource(); int i 0; private void Form1_Load(object sender, EventArgs e) { //初始化绑定任务取消令牌 t1 new Task(DoWork, cts.Token); } public string F1() { Console.WriteLine(F1); return 哈兰德; } public void DoWork() { Console.WriteLine(dowork); //未收到取消指令循环刷新UI while (!cts.IsCancellationRequested) { Invoke(new Action(() { label1.Text i.ToString(); })); i; } } //启动任务 private void button1_Click(object sender, EventArgs e) { Console.WriteLine(是否取消结束 t1.IsCanceled); Console.WriteLine(是否执行完成 t1.IsCompleted); Console.WriteLine(是否异常中断 t1.IsFaulted); if (t1.IsCompleted) { //任务完成重置通行证和任务 cts new CancellationTokenSource(); t1 new Task(DoWork, cts.Token); } t1.Start(); } //取消任务 private void button2_Click(object sender, EventArgs e) { cts.Cancel(); } } }Task获取异步任务返回结果笔记承接承接上一篇Task基础语法本节课核心获取有返回值Task异步执行结果两大取值方案① Result属性取值阻塞UI ② ContinueWith回调取值不阻塞UI项目推荐窗体控件button1触发异步任务无额外控件二、前置知识点泛型Task2.1 普通Task VS 泛型TaskTask无返回值异步任务只执行逻辑不能返回数据TaskTResult泛型异步任务带有返回值TResult为返回值数据类型string、int、对象获取返回值专属属性.Result只有泛型Task可以调用Result2.2 Task三种创建方式回顾原代码注释遗留基础写法复习三种创建任务方式//1.绑定外部无参方法 Task t1 new Task(F1); t1.Start(); //2.静态Run方法创建自动执行 Task.Run(() { Console.WriteLine(Run); }); //3.任务工厂创建 Task.Factory.StartNew(() { Console.WriteLine(Factory); });三、方案一Result属性获取任务结果阻塞UI3.1 完整代码拆分//创建字符串返回值的泛型异步任务 Taskstring t1 new Taskstring(() { //模拟耗时死循环任务长时间执行 //while (true) //{ } return 魔笛-莫迪老仙; }); t1.Start(); //直接读取任务返回结果 Console.WriteLine(t1.Result ssss);3.2 核心重难点必考阻塞特性代码执行到t1.Result时主线程立刻阻塞暂停所有页面响应、UI卡死阻塞原理主线程会一直等待异步任务执行完毕拿到返回值之后才继续向下执行代码致命缺点WinForm中严禁直接使用Result取值长时间任务直接造成程序未响应适用场景极短耗时任务任务瞬间执行完毕不会感知卡顿四、方案二ContinueWith回调获取结果非阻塞4.1 方法定义ContinueWith()任务延续回调方法执行逻辑等待前置任务t1完全执行结束自动触发回调函数不会阻塞主线程页面流畅不卡顿WinForm官方推荐写法回调内部参数t就是执行完毕的原任务对象t14.2 逐行拆解代码private void button1_Click(object sender, EventArgs e) { //创建返回字符串的泛型异步任务 Taskstring t1 new Taskstring(() { //模拟长时间耗时任务不会卡死窗体 //while (true) { } return 魔笛-莫迪老仙; }); t1.Start(); //任务延续回调t1执行完成后自动执行内部逻辑 t1.ContinueWith(t { //回调参数t 执行完毕的t1任务 //在回调内部读取Result不会阻塞UI主线程 Console.WriteLine(t.Result); }); }.3 执行流程梳理点击按钮主线程创建泛型任务t1启动异步任务主线程直接放行继续响应UI操作后台异步执行t1业务逻辑返回结果t1执行完毕自动触发ContinueWith回调回调内部读取Result打印结果全程不阻塞UI五、两种取值方式对比考试背诵取值方式是否阻塞UI优缺点使用场景Task.Result✅ 阻塞主线程、UI卡死代码简单阻塞程序极易造成程序未响应瞬时执行、极短耗时任务ContinueWith回调❌ 完全不阻塞UI异步回调界面流畅代码解耦所有异步取值、项目正式开发六、易错坑点汇总普通Task不能调用Result只有泛型TaskT才有返回值禁止在主线程直接读取Result必定造成界面卡顿ContinueWith内部的参数t就是执行完成的原任务实例二者是同一个对象异步任务死循环while(true)Result取值永久阻塞ContinueWith永远不会触发回调七、整合完整版可运行代码using System; using System.Threading.Tasks; using System.Windows.Forms; namespace _5如何获取异步任务结果 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { //创建带字符串返回值的异步任务 Taskstring t1 new Taskstring(() { //耗时死循环测试Result永久阻塞ContinueWith永不执行 //while (true) { } return 魔笛-莫迪老仙; }); t1.Start(); //方式1主线程取值阻塞UI不推荐 //Console.WriteLine(t1.Result ssss); //方式2任务回调取值不阻塞UI推荐 t1.ContinueWith(t { Console.WriteLine(t.Result); }); } //基础测试方法 public void F1() { Console.WriteLine(F1); } } }Task实现进度条启停暂停重置例子笔记承接承接Task基础、多任务等待系列笔记对比上期原生Thread进度条本次使用Task异步任务取消令牌暂停标记实现进度条功能启动、暂停、继续、强制重置修复原代码拼写bug、重启卡死逻辑漏洞窗体控件ProgressBar进度条、button1启动、button2暂停、button3继续、button4终止重置二、全局变量释义必考全局管控任务状态、暂停状态、取消权限逐行释义修正原代码注释错误namespace _2使Task实现进度 { public partial class Form1 : Form { public Form1() { InitializeComponent(); //窗体初始化仅启用启动按钮其余置灰防止乱点报错 button2.Enabled false; button3.Enabled false; button4.Enabled false; } //1.暂停标记false运行、true暂停自定义软暂停标识 bool pause false; //2.取消令牌源Task专属安全取消器安全终止异步任务 CancellationTokenSource cts; //3.进度计数变量 int i 0; //4.全局异步任务对象管控进度条任务 //修复原代码拼写错误tast → task Task task;三、核心执行逻辑3.1 循环三重判定条件while (!cts.IsCancellationRequested !pause i100)!cts.IsCancellationRequested未点击终止未收到取消指令!pause暂停标识关闭允许进度运行i100进度未满100继续刷新3.2 双重停止条件进度满100 || 触发取消令牌 → 清空进度、复位计数四、四大按钮事件逐行拆分4.1 Button1启动进度任务核心每次启动必须新建取消令牌绑定Task任务规避令牌复用报错增加异常捕获防止跨线程UI崩溃private void button1_Click(object sender, EventArgs e) { //重新创建取消通行证一个Task对应一个cts禁止复用旧令牌 cts new CancellationTokenSource(); //实例化异步任务绑定业务逻辑取消令牌 task new Task(() { //三重条件未取消、未暂停、进度未满 while (!cts.IsCancellationRequested !pause i 100) { Thread.Sleep(100);//模拟业务耗时放慢进度 try { //跨线程刷新UITask属于子线程必须Invoke切主线程 Invoke(new Action(() { progressBar1.Value i; })); } catch (Exception) { //捕获窗体销毁、线程抢占异常防止程序闪退 Console.WriteLine(UI刷新异常); } i;//进度自增 } //进度完成 或者 主动终止任务重置进度 if (i 100 || cts.IsCancellationRequested) { Invoke(new Action(() { progressBar1.Value 0; i 0; })); } }, cts.Token);//绑定取消令牌 task.Start();//启动异步任务 //按钮互斥锁定 button1.Enabled false; button2.Enabled true; button4.Enabled true; }4.2 Button2暂停进度private void button2_Click(object sender, EventArgs e) { pause true; //开启暂停标记阻断while循环 //切换按钮状态 button2.Enabled false; button3.Enabled true; }4.3 Button3恢复进度修复原代码逻辑bug原代码缺陷直接调用button1_Click重启任务会重复创建Task、造成多线程叠加、进度加速错乱补齐原理批注private void button3_Click(object sender, EventArgs e) { pause false;//关闭暂停标记放行while循环 //⚠️原代码问题直接调用button1_Click会重新创建任务叠加旧任务进度跳动错乱 //button1_Click(null,null); //优化仅恢复按钮状态原有任务继续执行不重复创建线程 button3.Enabled false; button2.Enabled true; button4.Enabled true; }4.4 Button4强制终止全局复位private void button4_Click(object sender, EventArgs e) { cts.Cancel();//发送取消指令终止异步任务循环 //复位全部按钮 button1.Enabled true; button2.Enabled false; button3.Enabled false; button4.Enabled false; //清空全局状态 progressBar1.Value 0; i 0; pause false; }五、重难点辨析考试高频5.1 Task进度条 VS Thread进度条原生Thread需要手动管控线程状态无自带取消令牌终止粗暴、容易内存泄漏Task版本自带CancellationTokenSource安全取消托管线程资源可控性更强代码简洁项目首选5.2 两套暂停机制区别上期Thread案例使用ManualResetEventSlim信号阻塞线程硬件级阻塞本期Task案例自定义bool变量逻辑拦截暂停软暂停写法更简单5.3 原代码Bug汇总拼写错误全局任务变量tast→ 正确task恢复按钮逻辑错误重启任务造成线程叠加、进度加速错乱异常空捕获原有catch空代码无日志提示不利于排错未规范释放cts资源长期运行轻微内存泄漏六、完整修复版可直接运行代码using System; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace _2使Task实现进度 { public partial class Form1 : Form { public Form1() { InitializeComponent(); //初始化按钮锁定 button2.Enabled false; button3.Enabled false; button4.Enabled false; } bool pause false; //自定义暂停标记 CancellationTokenSource cts;//任务取消令牌 int i 0; Task task;//修复拼写错误 private void button1_Click(object sender, EventArgs e) { cts new CancellationTokenSource(); task new Task(() { //三重循环判定 while (!cts.IsCancellationRequested !pause i 100) { Thread.Sleep(100); try { Invoke(new Action(() { progressBar1.Value i; })); } catch (Exception) { Console.WriteLine(UI刷新异常); } i; } //进度复位 if (i 100 || cts.IsCancellationRequested) { Invoke(new Action(() { progressBar1.Value 0; i 0; })); } }, cts.Token); task.Start(); button1.Enabled false; button2.Enabled true; button4.Enabled true; } //暂停 private void button2_Click(object sender, EventArgs e) { pause true; button2.Enabled false; button3.Enabled true; } //恢复修复逻辑bug private void button3_Click(object sender, EventArgs e) { pause false; button3.Enabled false; button2.Enabled true; button4.Enabled true; } //终止重置 private void button4_Click(object sender, EventArgs e) { cts.Cancel(); button1.Enabled true; button2.Enabled false; button3.Enabled false; button4.Enabled false; progressBar1.Value 0; i 0; pause false; } } }
C# WinForm Task异步任务+Task获取异步任务返回结果+Task实现进度条启停暂停重置
笔记承接承接Thread线程、线程信号案例Task是.NET高阶异步封装基于线程池封装相比原生Thread用法更简单、自带状态监控、自带取消机制是目前主流异步写法全文清理冗余代码、修复模糊注释、拆分多层泛型任务适配课堂考试窗体控件Label标签、button1(启动任务)、button2(取消任务)一、精简引用命名空间剔除全部无效冗余引用保留运行必备依赖标注每一项作用//基础系统命名空间 using System; //✅Task异步任务专属命名空间 using System.Threading.Tasks; //✅线程、取消令牌依赖 using System.Threading; //✅WinForm窗体控件 using System.Windows.Forms;二、全局变量释义全局声明任务对象、取消通行证实现启停、取消复用逐句拆解namespace _4Task基础 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } //1.声明异步任务对象管控异步任务状态、启动、执行 Task t1 null; //2.异步任务取消令牌源俗称【取消通行证】 //作用安全终止Task异步任务禁止暴力销毁线程官方推荐取消方案 CancellationTokenSource cts new CancellationTokenSource(); //计数变量页面自增数字 int i 0;三、Task三大创建方式考试必考原代码大量冗余注释、重复示例拆分整理三种创建方式优先级从低→高按课堂掌握权重排序3.1 方式一new Task() 实例化创建手动启动特点手动new创建必须调用.Start()才会执行任务灵活性最高可以绑定取消令牌3.1.1 基础无参写法//完整版传递Action委托 t1 new Task(new Action(() { })); //语法糖简化写法常用 t1 new Task(() { }); //绑定外部方法课堂重点、项目常用 t1 new Task(DoWork);3.1.2 带参数任务//第二个参数传入异步任务实参 t1 new Task((obj) { Console.WriteLine(obj); },hello);3.1.3 绑定取消令牌本案例核心//cts.Token传递取消通行证 //给异步任务绑定取消权限后续可以通过cts.Cancel()终止任务 t1 new Task(DoWork, cts.Token);3.2 方式二Task.Run() 静态创建自动执行特点调用方法直接自动启动任务无需手动Start代码最简开发最常用分为无返回值、有返回值、嵌套任务3.2.1 无返回值委托//绑定外部方法最简写法必须掌握 Task.Run(F1);3.2.2 基础返回值委托 FuncAction无返回值委托 | Func有返回值委托//返回字符串 Task.Run(new Funcstring(() { return 11; })); //返回整型 Task.Run(new Funcint(() 100));3.2.3 嵌套Task返回值难点任务返回值依旧是Task形成异步嵌套多用于链式异步调用//返回值为Task的异步任务 Task.Run(new FuncTask(() { return new Task(() { }); } ));3.3 方式三Task.Factory 任务工厂创建特点底层原生创建方式适配复杂调度写法繁琐课堂了解即可//无返回值 Task.Factory.StartNew(() {}); //带返回值 Task.Factory.StartNew(() gt;{ return 100; });四、泛型Task多层返回值拆解通俗易懂原代码多层嵌套晦涩难懂分层通俗解释解决看不懂嵌套问题Taskint普通泛型任务任务执行完毕返回数字100Taskstring任务执行完毕返回字符串11TaskTask外层任务执行完毕返回一个新的空任务TaskTaskint外层任务执行完毕返回一个带整型返回值的任务TaskTaskTask三层嵌套外层返回二级任务二级再返回三级任务工程极少使用仅语法演示五、业务方法拆分5.1 F1返回值测试方法/// summary /// 有返回值异步回调方法匹配Func委托 /// /summary public string F1() { Console.WriteLine(F1); return 哈兰德; }5.2 DoWork 主业务方法UI自增核心依靠取消令牌状态实现循环启停安全终止异步修复原代码注释歧义/// summary /// 异步主任务页面数字自增刷新label /// 依靠 cts.IsCancellationRequested 判断是否取消任务 /// /summary public void DoWork() { Console.WriteLine(dowork); //IsCancellationRequested取消请求标记 //false未收到取消指令任务继续执行 //true收到取消指令终止循环、停止任务 while (!cts.IsCancellationRequested) { //跨线程刷新UITask属于子线程禁止直接操作控件 Invoke(new Action(() { label1.Text i.ToString(); })); i; } }六、按钮事件逐行拆解6.1 button1启动异步任务重点任务完成必须重建取消令牌一个任务对应一个通行证复用令牌会报错private void button1_Click(object sender, EventArgs e) { //Task三大状态属性考试必背 t1.IsCanceled; //任务是否【主动取消】结束 t1.IsCompleted; //任务是否执行完毕正常结束/取消/异常都算完成 t1.IsFaulted; //任务是否报错、异常终止 //判定任务执行完成后重置令牌、重建任务 if (t1.IsCompleted) { cts new CancellationTokenSource();//新建取消通行证 t1 new Task(DoWork, cts.Token);//绑定全新通行证 } t1.Start();//手动启动异步任务 }6.2 button2取消异步任务private void button2_Click(object sender, EventArgs e) { //发送取消指令IsCancellationRequested 自动变为true //触发do-while循环退出安全停止任务 cts.Cancel(); }、核心重难点总结7.1 Task和Thread区别面试简答Thread原生线程粒度底层需要手动管控生命周期无自带取消、状态属性Task基于线程池封装上层异步封装自带完成、异常、取消状态语法简洁7.2 取消令牌规则CancellationTokenSource取消通行证管理器cts.Token通行证绑定Task任务禁止复用旧通行证每次新建Task必须重新new CancellationTokenSource7.3 Task三种创建对比new Task手动启动支持绑定取消令牌可控性最强Task.Run自动执行写法最简开发首选Task.Factory底层工厂复杂调度使用7.4 三大状态属性IsCompleted只要任务停止正常、报错、取消全部为trueIsCanceled只有主动调用Cancel取消任务才为trueIsFaulted代码报错、抛出异常任务中断为true八、整理精简可直接运行完整版代码using System; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace _4Task基础 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } Task t1 null; //异步取消通行证 CancellationTokenSource cts new CancellationTokenSource(); int i 0; private void Form1_Load(object sender, EventArgs e) { //初始化绑定任务取消令牌 t1 new Task(DoWork, cts.Token); } public string F1() { Console.WriteLine(F1); return 哈兰德; } public void DoWork() { Console.WriteLine(dowork); //未收到取消指令循环刷新UI while (!cts.IsCancellationRequested) { Invoke(new Action(() { label1.Text i.ToString(); })); i; } } //启动任务 private void button1_Click(object sender, EventArgs e) { Console.WriteLine(是否取消结束 t1.IsCanceled); Console.WriteLine(是否执行完成 t1.IsCompleted); Console.WriteLine(是否异常中断 t1.IsFaulted); if (t1.IsCompleted) { //任务完成重置通行证和任务 cts new CancellationTokenSource(); t1 new Task(DoWork, cts.Token); } t1.Start(); } //取消任务 private void button2_Click(object sender, EventArgs e) { cts.Cancel(); } } }Task获取异步任务返回结果笔记承接承接上一篇Task基础语法本节课核心获取有返回值Task异步执行结果两大取值方案① Result属性取值阻塞UI ② ContinueWith回调取值不阻塞UI项目推荐窗体控件button1触发异步任务无额外控件二、前置知识点泛型Task2.1 普通Task VS 泛型TaskTask无返回值异步任务只执行逻辑不能返回数据TaskTResult泛型异步任务带有返回值TResult为返回值数据类型string、int、对象获取返回值专属属性.Result只有泛型Task可以调用Result2.2 Task三种创建方式回顾原代码注释遗留基础写法复习三种创建任务方式//1.绑定外部无参方法 Task t1 new Task(F1); t1.Start(); //2.静态Run方法创建自动执行 Task.Run(() { Console.WriteLine(Run); }); //3.任务工厂创建 Task.Factory.StartNew(() { Console.WriteLine(Factory); });三、方案一Result属性获取任务结果阻塞UI3.1 完整代码拆分//创建字符串返回值的泛型异步任务 Taskstring t1 new Taskstring(() { //模拟耗时死循环任务长时间执行 //while (true) //{ } return 魔笛-莫迪老仙; }); t1.Start(); //直接读取任务返回结果 Console.WriteLine(t1.Result ssss);3.2 核心重难点必考阻塞特性代码执行到t1.Result时主线程立刻阻塞暂停所有页面响应、UI卡死阻塞原理主线程会一直等待异步任务执行完毕拿到返回值之后才继续向下执行代码致命缺点WinForm中严禁直接使用Result取值长时间任务直接造成程序未响应适用场景极短耗时任务任务瞬间执行完毕不会感知卡顿四、方案二ContinueWith回调获取结果非阻塞4.1 方法定义ContinueWith()任务延续回调方法执行逻辑等待前置任务t1完全执行结束自动触发回调函数不会阻塞主线程页面流畅不卡顿WinForm官方推荐写法回调内部参数t就是执行完毕的原任务对象t14.2 逐行拆解代码private void button1_Click(object sender, EventArgs e) { //创建返回字符串的泛型异步任务 Taskstring t1 new Taskstring(() { //模拟长时间耗时任务不会卡死窗体 //while (true) { } return 魔笛-莫迪老仙; }); t1.Start(); //任务延续回调t1执行完成后自动执行内部逻辑 t1.ContinueWith(t { //回调参数t 执行完毕的t1任务 //在回调内部读取Result不会阻塞UI主线程 Console.WriteLine(t.Result); }); }.3 执行流程梳理点击按钮主线程创建泛型任务t1启动异步任务主线程直接放行继续响应UI操作后台异步执行t1业务逻辑返回结果t1执行完毕自动触发ContinueWith回调回调内部读取Result打印结果全程不阻塞UI五、两种取值方式对比考试背诵取值方式是否阻塞UI优缺点使用场景Task.Result✅ 阻塞主线程、UI卡死代码简单阻塞程序极易造成程序未响应瞬时执行、极短耗时任务ContinueWith回调❌ 完全不阻塞UI异步回调界面流畅代码解耦所有异步取值、项目正式开发六、易错坑点汇总普通Task不能调用Result只有泛型TaskT才有返回值禁止在主线程直接读取Result必定造成界面卡顿ContinueWith内部的参数t就是执行完成的原任务实例二者是同一个对象异步任务死循环while(true)Result取值永久阻塞ContinueWith永远不会触发回调七、整合完整版可运行代码using System; using System.Threading.Tasks; using System.Windows.Forms; namespace _5如何获取异步任务结果 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { //创建带字符串返回值的异步任务 Taskstring t1 new Taskstring(() { //耗时死循环测试Result永久阻塞ContinueWith永不执行 //while (true) { } return 魔笛-莫迪老仙; }); t1.Start(); //方式1主线程取值阻塞UI不推荐 //Console.WriteLine(t1.Result ssss); //方式2任务回调取值不阻塞UI推荐 t1.ContinueWith(t { Console.WriteLine(t.Result); }); } //基础测试方法 public void F1() { Console.WriteLine(F1); } } }Task实现进度条启停暂停重置例子笔记承接承接Task基础、多任务等待系列笔记对比上期原生Thread进度条本次使用Task异步任务取消令牌暂停标记实现进度条功能启动、暂停、继续、强制重置修复原代码拼写bug、重启卡死逻辑漏洞窗体控件ProgressBar进度条、button1启动、button2暂停、button3继续、button4终止重置二、全局变量释义必考全局管控任务状态、暂停状态、取消权限逐行释义修正原代码注释错误namespace _2使Task实现进度 { public partial class Form1 : Form { public Form1() { InitializeComponent(); //窗体初始化仅启用启动按钮其余置灰防止乱点报错 button2.Enabled false; button3.Enabled false; button4.Enabled false; } //1.暂停标记false运行、true暂停自定义软暂停标识 bool pause false; //2.取消令牌源Task专属安全取消器安全终止异步任务 CancellationTokenSource cts; //3.进度计数变量 int i 0; //4.全局异步任务对象管控进度条任务 //修复原代码拼写错误tast → task Task task;三、核心执行逻辑3.1 循环三重判定条件while (!cts.IsCancellationRequested !pause i100)!cts.IsCancellationRequested未点击终止未收到取消指令!pause暂停标识关闭允许进度运行i100进度未满100继续刷新3.2 双重停止条件进度满100 || 触发取消令牌 → 清空进度、复位计数四、四大按钮事件逐行拆分4.1 Button1启动进度任务核心每次启动必须新建取消令牌绑定Task任务规避令牌复用报错增加异常捕获防止跨线程UI崩溃private void button1_Click(object sender, EventArgs e) { //重新创建取消通行证一个Task对应一个cts禁止复用旧令牌 cts new CancellationTokenSource(); //实例化异步任务绑定业务逻辑取消令牌 task new Task(() { //三重条件未取消、未暂停、进度未满 while (!cts.IsCancellationRequested !pause i 100) { Thread.Sleep(100);//模拟业务耗时放慢进度 try { //跨线程刷新UITask属于子线程必须Invoke切主线程 Invoke(new Action(() { progressBar1.Value i; })); } catch (Exception) { //捕获窗体销毁、线程抢占异常防止程序闪退 Console.WriteLine(UI刷新异常); } i;//进度自增 } //进度完成 或者 主动终止任务重置进度 if (i 100 || cts.IsCancellationRequested) { Invoke(new Action(() { progressBar1.Value 0; i 0; })); } }, cts.Token);//绑定取消令牌 task.Start();//启动异步任务 //按钮互斥锁定 button1.Enabled false; button2.Enabled true; button4.Enabled true; }4.2 Button2暂停进度private void button2_Click(object sender, EventArgs e) { pause true; //开启暂停标记阻断while循环 //切换按钮状态 button2.Enabled false; button3.Enabled true; }4.3 Button3恢复进度修复原代码逻辑bug原代码缺陷直接调用button1_Click重启任务会重复创建Task、造成多线程叠加、进度加速错乱补齐原理批注private void button3_Click(object sender, EventArgs e) { pause false;//关闭暂停标记放行while循环 //⚠️原代码问题直接调用button1_Click会重新创建任务叠加旧任务进度跳动错乱 //button1_Click(null,null); //优化仅恢复按钮状态原有任务继续执行不重复创建线程 button3.Enabled false; button2.Enabled true; button4.Enabled true; }4.4 Button4强制终止全局复位private void button4_Click(object sender, EventArgs e) { cts.Cancel();//发送取消指令终止异步任务循环 //复位全部按钮 button1.Enabled true; button2.Enabled false; button3.Enabled false; button4.Enabled false; //清空全局状态 progressBar1.Value 0; i 0; pause false; }五、重难点辨析考试高频5.1 Task进度条 VS Thread进度条原生Thread需要手动管控线程状态无自带取消令牌终止粗暴、容易内存泄漏Task版本自带CancellationTokenSource安全取消托管线程资源可控性更强代码简洁项目首选5.2 两套暂停机制区别上期Thread案例使用ManualResetEventSlim信号阻塞线程硬件级阻塞本期Task案例自定义bool变量逻辑拦截暂停软暂停写法更简单5.3 原代码Bug汇总拼写错误全局任务变量tast→ 正确task恢复按钮逻辑错误重启任务造成线程叠加、进度加速错乱异常空捕获原有catch空代码无日志提示不利于排错未规范释放cts资源长期运行轻微内存泄漏六、完整修复版可直接运行代码using System; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace _2使Task实现进度 { public partial class Form1 : Form { public Form1() { InitializeComponent(); //初始化按钮锁定 button2.Enabled false; button3.Enabled false; button4.Enabled false; } bool pause false; //自定义暂停标记 CancellationTokenSource cts;//任务取消令牌 int i 0; Task task;//修复拼写错误 private void button1_Click(object sender, EventArgs e) { cts new CancellationTokenSource(); task new Task(() { //三重循环判定 while (!cts.IsCancellationRequested !pause i 100) { Thread.Sleep(100); try { Invoke(new Action(() { progressBar1.Value i; })); } catch (Exception) { Console.WriteLine(UI刷新异常); } i; } //进度复位 if (i 100 || cts.IsCancellationRequested) { Invoke(new Action(() { progressBar1.Value 0; i 0; })); } }, cts.Token); task.Start(); button1.Enabled false; button2.Enabled true; button4.Enabled true; } //暂停 private void button2_Click(object sender, EventArgs e) { pause true; button2.Enabled false; button3.Enabled true; } //恢复修复逻辑bug private void button3_Click(object sender, EventArgs e) { pause false; button3.Enabled false; button2.Enabled true; button4.Enabled true; } //终止重置 private void button4_Click(object sender, EventArgs e) { cts.Cancel(); button1.Enabled true; button2.Enabled false; button3.Enabled false; button4.Enabled false; progressBar1.Value 0; i 0; pause false; } } }