收藏 分享(赏)

走进异步编程的世界-在WinForm中执行异步操作概要.docx

上传人:kaixinyidian 文档编号:12024450 上传时间:2021-07-30 格式:DOCX 页数:14 大小:72.80KB
下载 相关 举报
走进异步编程的世界-在WinForm中执行异步操作概要.docx_第1页
第1页 / 共14页
走进异步编程的世界-在WinForm中执行异步操作概要.docx_第2页
第2页 / 共14页
走进异步编程的世界-在WinForm中执行异步操作概要.docx_第3页
第3页 / 共14页
走进异步编程的世界-在WinForm中执行异步操作概要.docx_第4页
第4页 / 共14页
走进异步编程的世界-在WinForm中执行异步操作概要.docx_第5页
第5页 / 共14页
点击查看更多>>
资源描述

1、走进异步编程的世界-在 WinForm 中执行异步操作这是继开始接触 async/await异步编程、走进异步编程的世界-剖析异步方法后的第三篇。主要介绍在 WinForm 中如何执行异步操作。目录在WinForm中执行异步操作在WinForm中使用异步 Lambda 表达式 一个完整的WinForm 程序另一种异步方式 -BackgroundWorker 类、在 WinForm程序中执行异步操作下面通过窗体示例演示以下操作-点击按钮后:将按钮禁用,并将标签内容改成:“Doing”(表示执行中);线程挂起3秒(模拟耗时操作);启用按钮,将标签内容改为:Complete”(表示执行完成)。1 p

2、ublic partial class Form1 : Form2 3 public Form1()4 5 InitializeComponent();6 78 private void btnDo_Click( object sender, EventArgs e)9 一10 btnDo.Enabled =false ;11 lblText.Text =Doing;13 Thread.Sleep(1415 btnDo.Enabled=16 IblText.Text =17 18 3000);true ;Complete;可是执行结果却是:ndow5hornnsMpplicationl rr-

3、omnl审反管仔无聊图1-1【发现的问题】好像没有变成Doing”?并且拖动窗口的时候卡住不动了 ?3秒后突然变到想拖动到的位置?同时文本变成 Complete ?【分析】GUI程序在设计中要求所有的显示变化都必须在主GUI线程中完成,如点击事件和移动窗体。Windows程序时通过 消息来实现,消息放入消息泵管理的消息队列中。点击按钮时, 按钮的Click消息放入消息队列。消息泵从队列中移除该消息,并开始处理点击事件的代码, 即btnDo_Click 事件的代码。btnDo_Click 事件会将触发行为的消息放入队列,但在 btnDo_Click 时间处理程序完全退出 前(线程挂起3秒退出前)

4、,消息都无法执行。(3秒后)接着所有行为都发生了,但速度太快肉 眼无法分辨才没有发现标签改成 “Doing”。点击按钮消息泵图1-2点击事件消息泵图1-3点击事件具体执行过程现在我们加入async/await 特性1 public partial class Forml : Form2 3 public Form1()4 5 InitializeComponent();6 78 private async void btnDo_Click( object sender, EventArgs e)9 一10 btnDo.Enabled =false ;11 lblText.Text =Doing

5、;1213 await Task.Delay( 3000);1415 btnDo.Enabled =true ;16 lblText.Text =Complete;17 18 4反骨仔 - x spreadsheetl ,csv ClassLibraryl MainWindow,Karrindowsl btnDo Clickfobject sender, EventArgs e,无聊IJ -I图1-4现在,就是原先希望看到的效果。【分析】btnDo_Click 事件处理程序先将前两条消息压入队列,然后将自己从处理器移出,在 3秒后(等待空闲任务完成后 Task.Delay )再将自己压入队列。

6、这样可以保持响应,并保证所有 的消息可以在线程挂起的时间内被处理。12 34 56 78 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 361.1 Task.YieldTask.Yield方法创建一个立刻返回的awaitable 。等待一个Yield可以让异步方法在执行后续部分的同时返回到调用方法。可以将其理解为离开当前消息队列,回到队列末尾,让 CPU有时间处理其它任务。class Program static void Main( string 口 args) const in

7、t num = 100000Q var t = DoStuff.Yield1000(num);Loop(num /10);Loop(num /10);Loop(num /10);Console.WriteLine($Sum: t.Result”);Console.Read();/ /循环/ / private static void Loop( int num) for ( var i =0; i num; i+);internal static class DoStuffpublic static async Task Yield1000( int n) var sum = 0;for (

8、int i =0; i Do(false , Doing);await Task.Delay( 3000);Do(true , Finished);text)private void Do( bool isEnable, string btnDo.Enabled = isEnable;21 lblText.Text = text;2223 还是原来的配方,还是熟悉的味道,还是原来哪个窗口,变的只是内涵。Forml 0图2-1MainWindc123456789101112131415161718192021三、一个完整的 WinForm 程序现在在原来的基础上添加了进度条,以及取消按钮publ

9、ic partial class Form1 : Form private CancellationTokenSource _source;private CancellationToken _token;public Form1()InitializeComponent();/ / Do按钮事件/ / / private async void btnDo_Click( object sender, EventArgs e) .btnDo.Enabled =false ;_source =newCancellationTokenSource();_token = _source.Token;2

10、2232425进度值2627282930313233343536var completedPercent =0; / 完成百分比const int time = 10; 循环次数const int timePercent =100 / time;进度条每次增加的for ( var i =0; i time; i+)if (_token.IsCancellationRequested) break;tryawait Task.Delay( 500, _token);37383940414243444546474849completedPercent = (i +1) * timePercent;

11、catch (Exception)completedPercent = i * timePercent;finallyprogressBar.Value = completedPercent;var msg = _token.IsCancellationRequested ? $进度为:completedPercent% 已被取消! : $ 已经完成; 5051 MessageBox.Show(msg,信息”);5253progressBar.Value =0;54InitTool();555657 /summary58 /初始化窗体的工具控件59 /summary60 private voi

12、d InitTool()61 62 progressBar.Value =0;63 btnDo.Enabled =true ;64656667686970717273747576777879btnCancel.Enabled =true ;/取消事件private void btnCancel_Click(if (btnDo.Enabled)btnCancel.Enabled =returnfalse_source.Cancel();object sender, EventArgs e)C ancel图3-1四、另一种异步方式-BackgroundWorker 类与async/await 不同

13、的是,你有时候可能需要一个额外的线程,在后台持续完成某项任务,并 不时与主线程通信,这时就需要用到 BackgroundWorker 类。主要用于 GUI程序。书中的千言万语不及一个简单的示例。1 public partial class Form2 : Form2 private readonly BackgroundWorker _worker = newBackgroundWorker();45678910更新11public Form2()InitializeComponent();/ 设置 BackgroundWorker 属性 _worker.WorkerReportsProgre

14、ss =_worker.WorkerSupportsCancellation =true ;/能否报告进度true ; /是否支持异步取消121314/连接Backgroundworker对象的处理程序_worker.DoWork += _worker_DoWork;/开始执行后台操作时触发,即调用 BackgroundWorker.RunWorkerAsync 时触发15_worker.ProgressChanged += _worker_ProgressChanged;/调用 BackgroundWorker.ReportProgress(System.Int32) 时触发16_worke

15、r.RunWorkerCompleted +=_worker_RunWorkerCompleted; /当后台操作已完成、被取消或引发异常时触发1718192021222324/ / /当后台操作已完成、被取消或引发异常时发生private void _worker_RunWorkerCompleted( object sender,RunWorkerCompletedEventArgs e)2526 MessageBox.Show(e.Cancelled ? $进程已被取消:progressBar.Value% : $ 进程执行完成:progressBar.Value%);272829303

16、1 发生32333435progressBar.Value =/0;调用 BackgroundWorker.ReportProgress(System.Int32) 时private void _worker_ProgressChanged( object sender,ProgressChangedEventArgs e)3637 progressBar.Value = e.ProgressPercentage;/异步任务的进度百分比383940/ 41/开始执行后台操作触发,即调用BackgroundWorker.RunWorkerAsync 时发生42/43/44/45private s

17、tatic void _worker_DoWork( object sender,DoWorkEventArgs e)4647 var worker = sender as BackgroundWorker;48 if (worker = null )49 50 return ;51 5253for (var i =0; i 10; i+)5455 /判断程序是否已请求取消后台操作56 if (worker.CancellationPending)57 58 e.Cancel =true ;59 break;60 6162worker.ReportProgress(i +1) * 10); 触

18、发BackgroundWorker.ProgressChanged 事件63Thread.Sleep(250);/ 线程挂起 250 毫秒64656667private void btnDo_Click( object sender, EventArgs e)6869 /判断BackgroundWorker是否正在执行异步操作70 if (!_worker.IsBusy)71 72 _worker.RunWorkerAsync();/ 开始执行后台操作73 一74 7576private void btnCancel_Click( object sender, EventArgs e)77 一78 _worker.CancelAsync();/请求取消挂起的后台操作79 80 9 Form2 XDoCancel

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 网络科技 > 其他相关文档

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报