好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

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

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

 在开发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,但是对应需要显示更负责的数据时比较麻烦;

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

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

 

 

 

标签:  异步 ,  winform ,  lamada ,  c#

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于实现 winform 异步跨线程访问UI控件的详细内容...

  阅读:54次