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

上传人:b****0 文档编号:723184 上传时间:2022-10-12 格式:DOCX 页数:14 大小:454.39KB
下载 相关 举报
走进异步编程的世界在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页
点击查看更多>>
下载资源
资源描述

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

《走进异步编程的世界在WinForm中执行异步操作概要.docx》由会员分享,可在线阅读,更多相关《走进异步编程的世界在WinForm中执行异步操作概要.docx(14页珍藏版)》请在冰豆网上搜索。

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

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

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

   这是继《开始接触async/await异步编程》、《走进异步编程的世界-剖析异步方法》后的第三篇。

主要介绍在WinForm中如何执行异步操作。

 

•在WinForm中执行异步操作

•在WinForm中使用异步Lambda表达式

•一个完整的WinForm程序

•另一种异步方式-BackgroundWorker类 

一、在WinForm程序中执行异步操作

  下面通过窗体示例演示以下操作-点击按钮后:

    ①将按钮禁用,并将标签内容改成:

“Doing”(表示执行中);

    ②线程挂起3秒(模拟耗时操作);

    ③启用按钮,将标签内容改为:

“Complete”(表示执行完成)。

1publicpartialclassForm1:

Form

2{

3publicForm1()

4{

5InitializeComponent();

6}

7

8privatevoidbtnDo_Click(objectsender,EventArgse)

9{

10btnDo.Enabled=false;

11lblText.Text=@"Doing";

12

13Thread.Sleep(3000);

14

15btnDo.Enabled=true;

16lblText.Text=@"Complete";

17}

18}

  可是执行结果却是:

图1-1

 

  【发现的问题】

    ①好像没有变成“Doing”?

    ②并且拖动窗口的时候卡住不动了?

    ③3秒后突然变到想拖动到的位置?

    ④同时文本变成“Complete”?

 

  【分析】GUI程序在设计中要求所有的显示变化都必须在主GUI线程中完成,如点击事件和移动窗体。

Windows 程序时通过消息来实现,消息放入消息泵管理的消息队列中。

点击按钮时,按钮的Click消息放入消息队列。

消息泵从队列中移除该消息,并开始处理点击事件的代码,即 btnDo_Click事件的代码。

  btnDo_Click事件会将触发行为的消息放入队列,但在 btnDo_Click时间处理程序完全退出前(线程挂起3秒退出前),消息都无法执行。

(3秒后)接着所有行为都发生了,但速度太快肉眼无法分辨才没有发现标签改成“Doing”。

图1-2点击事件

图1-3点击事件具体执行过程

  

  现在我们加入async/await特性。

1publicpartialclassForm1:

Form

2{

3publicForm1()

4{

5InitializeComponent();

6}

7

8privateasyncvoidbtnDo_Click(objectsender,EventArgse)

9{

10btnDo.Enabled=false;

11lblText.Text=@"Doing";

12

13awaitTask.Delay(3000);

14

15btnDo.Enabled=true;

16lblText.Text=@"Complete";

17}

18}

图1-4

  现在,就是原先希望看到的效果。

  【分析】btnDo_Click事件处理程序先将前两条消息压入队列,然后将自己从处理器移出,在3秒后(等待空闲任务完成后Task.Delay)再将自己压入队列。

这样可以保持响应,并保证所有的消息可以在线程挂起的时间内被处理。

 

 1.1Task.Yield

  Task.Yield方法创建一个立刻返回的awaitable。

等待一个Yield可以让异步方法在执行后续部分的同时返回到调用方法。

可以将其理解为离开当前消息队列,回到队列末尾,让CPU有时间处理其它任务。

1classProgram

2{

3staticvoidMain(string[]args)

4{

5constintnum=1000000;

6vart=DoStuff.Yield1000(num);

7

8Loop(num/10);

9Loop(num/10);

10Loop(num/10);

11

12Console.WriteLine($"Sum:

{t.Result}");

13

14Console.Read();

15}

16

17///

18///循环

19///

20///

21privatestaticvoidLoop(intnum)

22{

23for(vari=0;i

24}

25}

26

27internalstaticclassDoStuff

28{

29publicstaticasyncTaskYield1000(intn)

30{

31varsum=0;

32for(inti=0;i

33{

34sum+=i;

35if(i%1000==0)

36{

37awaitTask.Yield();//创建异步产生当前上下文的等待任务

38}

39}

40

41returnsum;

42}

43}

 图1.1-1

  上述代码每执行1000次循环就调用Task.Yield方法创建一个等待任务,让处理器有时间处理其它任务。

该方法在GUI程序中是比较有用的。

 

二、在WinForm中使用异步Lambda表达式

  将刚才的窗口程序的点击事件稍微改动一下。

1publicpartialclassForm1:

Form

2{

3publicForm1()

4{

5InitializeComponent();

6

7//async(sender,e)异步表达式

8btnDo.Click+=async(sender,e)=>

9{

10Do(false,"Doing");

11

12awaitTask.Delay(3000);

13

14Do(true,"Finished");

15};

16}

17

18privatevoidDo(boolisEnable,stringtext)

19{

20btnDo.Enabled=isEnable;

21lblText.Text=text;

22}

23}

  还是原来的配方,还是熟悉的味道,还是原来哪个窗口,变的只是内涵。

图2-1

 

三、一个完整的WinForm程序

  现在在原来的基础上添加了进度条,以及取消按钮。

1publicpartialclassForm1:

Form

2{

3privateCancellationTokenSource_source;

4privateCancellationToken_token;

5

6publicForm1()

7{

8InitializeComponent();

9}

10

11///

12///Do按钮事件

13///

14///

15///

16privateasyncvoidbtnDo_Click(objectsender,EventArgse)

17{

18btnDo.Enabled=false;

19

20_source=newCancellationTokenSource();

21_token=_source.Token;

22

23varcompletedPercent=0;//完成百分比

24constinttime=10;//循环次数

25constinttimePercent=100/time;//进度条每次增加的进度值

26

27for(vari=0;i

28{

29if(_token.IsCancellationRequested)

30{

31break;

32}

33

34try

35{

36awaitTask.Delay(500,_token);

37completedPercent=(i+1)*timePercent;

38}

39catch(Exception)

40{

41completedPercent=i*timePercent;

42}

43finally

44{

45progressBar.Value=completedPercent;

46}

47}

48

49varmsg=_token.IsCancellationRequested?

$"进度为:

{completedPercent}%已被取消!

":

$"已经完成";

50

51MessageBox.Show(msg,@"信息");

52

53progressBar.Value=0;

54InitTool();

55}

56

57///

58///初始化窗体的工具控件

59///

60privatevoidInitTool()

61{

62progressBar.Value=0;

63btnDo.Enabled=true;

64btnCancel.Enabled=true;

65}

66

67///

68///取消事件

69///

70///

71///

72privatevoidbtnCancel_Click(objectsender,EventArgse)

73{

74if(btnDo.Enabled)return;

75

76btnCancel.Enabled=false;

77_source.Cancel();

78}

79}

 图3-1

 

四、另一种异步方式-BackgroundWorker类

  与async/await不同的是,你有时候可能需要一个额外的线程,在后台持续完成某项任务,并不时与主线程通信,这时就需要用到 BackgroundW

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

当前位置:首页 > 解决方案 > 商业计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1