注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

天涯倦客的博客

祝福你朋友永远快乐!

 
 
 

日志

 
 

实现 winform 异步跨线程访问UI控件  

2013-05-09 11:02:16|  分类: WinForm |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

转自:http://www.cnblogs.com/steven_jiangxf/archive/2013/05/09/steven.html

在开发winform时经常会用到多线程防止界面出现假死现象,比如当你单击某个按钮时,需要执行很多代码,但是在执行过程中想实时的将当前执行的情况报告给用户,类型进度条或文本什么的。

这个时候很显然,如果你把要实现的内容放在按钮方法里时,其实界面要等这个按钮执行完后才能输出来,这个时候就达不到我们的预期了;那么怎么才能解决问题呢。

我初略终结了一下有以下几种方法:

    1.采用BackgroundWorker控件,这个控件将要实时输出的内容写在事件中;

复制代码
 1 private void button1_Click(object sender, EventArgs e)
 2         {
 3             //异步执行逻辑
 4             backgroundWorker1.RunWorkerAsync();
 5         }
 6         private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
 7         {
 8             //实现业务逻辑
 9             int i = 5;
10             i = Math.Abs(i);
11             //报告当前处理进度
12             backgroundWorker1.ReportProgress(50);
13         }
14 
15         private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
16         {
17             //当前进度
18             int cuur = e.ProgressPercentage;
19             //实现跨线程控件的输出
20             this.label1.Text = cuur.ToString();
21         }
22 
23         private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
24         {
25             //执行完毕可以报告信息
26             this.label1.Text = "ok";
27         }
复制代码

   2.采用委托的方式实现灵活引用Invoke;

复制代码
 1         private void button2_Click(object sender, EventArgs e)
 2         {
 3             //异步执行逻辑
 4             Thread thread = new Thread(ThreadFunc);
 5             thread.IsBackground = true;
 6             thread.Start();
 7         }
 8         private void ThreadFunc()
 9         {
10             //实现业务逻辑
11             int i = 5;
12             i = Math.Abs(i);
13             //报告当前处理进度
14             SetLabel(i.ToString());
15         }
16         //定义委托
17         delegate void SetLabelHandler(string text);
18         //实现方法
19         private void SetLabel(string text)
20         {
21             if (InvokeRequired)
22             {
23                 Invoke(new SetLabelHandler(SetLabel), text);
24             }
25             else
26             {
27                 this.label1.Text = text;
28             }
29         }
复制代码

  3.采用Lamada表达式动态实现委托调用。

复制代码
 1         private void button3_Click(object sender, EventArgs e)
 2         {
 3             //异步执行逻辑
 4             Thread thread = new Thread(Func);
 5             thread.IsBackground = true;
 6             thread.Start();
 7         }
 8         private void Func()
 9         {
10             //实现业务逻辑
11             int i = 5;
12             i = Math.Abs(i);
13             //报告当前处理进度
14             AsyncUI(() => { label1.Text = i.ToString(); });
15         }
16         public void AsyncUI(Action action)
17         {
18             if (InvokeRequired)
19             {
20                 Invoke(action);
21             }
22             else
23             {
24                 action();
25             }
26         }
复制代码

 

以上是我总结的三种,至于有没有其他方法,欢迎大家来拍砖,在这里我想推荐的是第三种方法,这个方法最灵活。

下面来谈谈我对这三种的看法:

对应第一种方法:使用简单,拖控件就ok,但是对应需要显示更负责的数据时比较麻烦;

对应第二种方法:可以不用拖控件来自由定制,但是同第一种方法一样,如果需要显示更多控件数据,也要定义很多方法和委托,太冗余累赘;

对于第三种方法:我个人非常喜欢,代码在需要的时候动态使用,但是我也没有仔细分析该方法的性能问题。


  评论这张
 
阅读(843)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017