实现 winform 异步跨线程访问UI控件
1 在开发winform时经常会用到多线程防止界面出现假死现象,比如当你单击某个按钮时,需要执行很多代码,但是在执行过程中想实时的将当前执行的情况报告给用户,类型进度条或文本什么的。 2 3 这个时候很显然,如果你把要实现的内容放在按钮方法里时,其实界面要等这个按钮执行完后才能输出来,这个时候就达不到我们的预期了;那么怎么才能解决问题呢。 4 5 我初略终结了一下有以下几种方法: 6 7 1.采用BackgroundWorker控件,这个控件将要实时输出的内容写在事件中; 8 9 10 1 private void button1_Click(object sender, EventArgs e) 11 2 { 12 3 //异步执行逻辑 13 4 backgroundWorker1.RunWorkerAsync(); 14 5 } 15 6 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 16 7 { 17 8 //实现业务逻辑 18 9 int i = 5; 19 10 i = Math.Abs(i); 20 11 //报告当前处理进度 21 12 backgroundWorker1.ReportProgress(50); 22 13 } 23 14 24 15 private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 25 16 { 26 17 //当前进度 27 18 int cuur = e.ProgressPercentage; 28 19 //实现跨线程控件的输出 29 20 this.label1.Text = cuur.ToString(); 30 21 } 31 22 32 23 private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 33 24 { 34 25 //执行完毕可以报告信息 35 26 this.label1.Text = "ok"; 36 27 } 37 38 2.采用委托的方式实现灵活引用Invoke; 39 40 41 1 private void button2_Click(object sender, EventArgs e) 42 2 { 43 3 //异步执行逻辑 44 4 Thread thread = new Thread(ThreadFunc); 45 5 thread.IsBackground = true; 46 6 thread.Start(); 47 7 } 48 8 private void ThreadFunc() 49 9 { 50 10 //实现业务逻辑 51 11 int i = 5; 52 12 i = Math.Abs(i); 53 13 //报告当前处理进度 54 14 SetLabel(i.ToString()); 55 15 } 56 16 //定义委托 57 17 delegate void SetLabelHandler(string text); 58 18 //实现方法 59 19 private void SetLabel(string text) 60 20 { 61 21 if (InvokeRequired) 62 22 { 63 23 Invoke(new SetLabelHandler(SetLabel), text); 64 24 } 65 25 else 66 26 { 67 27 this.label1.Text = text; 68 28 } 69 29 } 70 71 3.采用Lamada表达式动态实现委托调用。 72 73 74 1 private void button3_Click(object sender, EventArgs e) 75 2 { 76 3 //异步执行逻辑 77 4 Thread thread = new Thread(Func); 78 5 thread.IsBackground = true; 79 6 thread.Start(); 80 7 } 81 8 private void Func() 82 9 { 83 10 //实现业务逻辑 84 11 int i = 5; 85 12 i = Math.Abs(i); 86 13 //报告当前处理进度 87 14 AsyncUI(() => { label1.Text = i.ToString(); }); 88 15 } 89 16 public void AsyncUI(Action action) 90 17 { 91 18 if (InvokeRequired) 92 19 { 93 20 Invoke(action); 94 21 } 95 22 else 96 23 { 97 24 action(); 98 25 } 99 26 } 100 101 102 103 以上是我总结的三种,至于有没有其他方法,欢迎大家来拍砖,在这里我想推荐的是第三种方法,这个方法最灵活。 104 105 下面来谈谈我对这三种的看法: 106 107 对应第一种方法:使用简单,拖控件就ok,但是对应需要显示更负责的数据时比较麻烦; 108 109 对应第二种方法:可以不用拖控件来自由定制,但是同第一种方法一样,如果需要显示更多控件数据,也要定义很多方法和委托,太冗余累赘; 110 111 对于第三种方法:我个人非常喜欢,代码在需要的时候动态使用,但是我也没有仔细分析该方法的性能问题。
posted on 2013-07-04 21:31 jian60521 阅读(1192) 评论(4) 编辑 收藏 举报