开发过程中,遇到了串口接收数据, socket接受数据,线程过程的数据需要显示到页面的时候,如果直接赋值,会报错。
这个时候需要用到委托,由主线程来操作界面的控件。
例子1
//测试的窗体
2 public class TestForm : Form
3 {
4 //创建一个Button对象
5 private Button button = new Button();
6 //构造函数
7 public TestForm()
8 {
9 //设置按钮的属性
10 button.Size = new Size(150, 100); //大小
11 button.Click += Button1_Clicked; //注册事件
12 button.Text = "点击开始测试"; //设置显示文本
13 this.Controls.Add(button); //添加到窗体上
14 this.Text = "多线程范例"; //设置窗体的标题栏文本
15 }
16 //按钮的Click事件响应方法
17 public void Button1_Clicked(object sender, EventArgs e)
18 {
19 //启动一个线程
20 new Thread(ThreadProc).Start();
21 }
22 //线程函数
23 public void ThreadProc()
24 {
25 //this.Invoke就是跨线程访问ui的方法,也是本文的范例
26 //首先invoke一个匿名委托,将button对象禁用
27 this.Invoke((EventHandler)delegate
28 {
29 button.Enabled = false;
30 });
31
32 //记录一个时间戳,以演示倒计时效果
33 int tick = Environment.TickCount;
34 while (Environment.TickCount - tick < 1000)
35 {
36 //跨线程调用更新窗体上控件的属性,这里是更新这个按钮对象的Text属性
37 this.Invoke((EventHandler)delegate
38 {
39 button.Text = (1000 - Environment.TickCount + tick).ToString() + "微秒后开始更新";
40 });
41 //做一个延迟,避免太快了,视觉效果不好。
42 Thread.Sleep(100);
43 }
44 //演示,10次数字递增显示
45 for (int i = 0; i < 10; i++)
46 {
47 this.Invoke((EventHandler)delegate
48 {
49 button.Text = i.ToString();
50 });
51 Thread.Sleep(200);
52 }
53 //虽然不是循环内,请不要忘记,你的调用依然在辅助线程中,所以,还是需要invoke的。
54 //还原状态,设置按钮的文本为初始状态,设置按钮可用。
55 this.Invoke((EventHandler)delegate
56 {
57 button.Text = "点击开始测试";
58 button.Enabled = true;
59 });
60 }
61 }
例子2
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace SQL_browser
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
/*
* 1.MethodInvoke和Action都是方法返回类型为空的委托.
* 2.MethodInvoker的原型定义为---> public delegate void MethodInvoker();
*/
//Delegate d1 = (MethodInvoker)delegate { };
//Delegate d2 = (MethodInvoker)(() => { });
//Delegate d3 = (Action)delegate { };
//Delegate d4 = (Action)(() => { });
Thread t = new Thread(() =>
{
Enumerable.Range(1, 10).ToList().ForEach(x =>
{
if (listBox1.InvokeRequired)
{
listBox1.Invoke((Action)(() =>
{
listBox1.Items.Add(string.Format("[{0}] executed 【 (Action)(() => {{ }}) 】", x));
}));
}
});
Enumerable.Range(11, 10).ToList().ForEach(x =>
{
if (listBox1.InvokeRequired)
{
listBox1.Invoke((Action)delegate
{
listBox1.Items.Add(string.Format("[{0}] executed 【 (Action)delegate {{ }} 】", x));
});
}
});
Enumerable.Range(21, 10).ToList().ForEach(x =>
{
if (listBox1.InvokeRequired)
{
listBox1.CCInvoke(() => //使用lambda表达式
{
listBox1.Items.Add(string.Format("[{0}] executed 【 lambda 】", x));
});
listBox1.CCInvoke(delegate //使用委托
{
listBox1.Items.Add(string.Format("[{0}] executed 【 delegate 】", x));
});
}
});
});
t.Start();
}
}
private void button2_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
Task taskWithFactoryAndState1 = Task.Factory.StartNew<List<int>>((stateObj) =>
{
List<int> ints = new List<int>();
for (int i = 0; i < (int)stateObj; i++)
{
ints.Add(i);
}
return ints;
}, 100).ContinueWith(ant =>
{
listBox1.DataSource = ant.Result;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
public static class ControlExtend
{
public static void CCInvoke(this Control control, Action action)
{
if (control.IsDisposed)
return;
try
{
control.Invoke((Delegate)action);
}
catch (ObjectDisposedException ode)
{
}
catch (InvalidOperationException iox)
{
}
}
}
}