先来看一个“想当然”的代码。
private void showDateTimeMethod() { while (true) { //显示当前时间 label1.Text = "当前时间 " + DateTime.Now.ToString(); //线程暂停 Thread.Sleep(1000); } } private void Form1_Load(object sender, EventArgs e) { //新建一个线程 Thread showDateTimethread = new Thread(new ThreadStart(showDateTimeMethod)); //该线程为后台线程 showDateTimethread.IsBackground = true; //线程启动 showDateTimethread.Start(); }
用我的大腿想想,上面的代码应该是对的,但是由于net苛刻的安全机制,showDateTimeMethod中的代码是有错误的。为了解决这个错误可以声明一个委托类型,实例化一个委托变量(这话听起来很拗口),并给这个委托变量指定函数引用。
方法一,使用命名方法
//声明一个委托类型,该委托类型无输入参数和输出参数 public delegate void ProcessDelegate(); //函数引用,label控件显示当前时间,输入参数无,输出参数无,和声明的委托类型形式一致 public void LabelShow() { label1.Text = "当前时间 " + DateTime.Now.ToString(); }
然后在线程中实例化一个委托变量,指向这个函数引用。
while (true) { //使用命名方法 ProcessDelegate showProcess = new ProcessDelegate(LabelShow); //调用label的invoke方法 label1.Invoke(showProcess); //线程暂停 Thread.Sleep(1000); }
这样的话就可以在窗体中看到当前的时间了。
方法二,使用匿名方法
刚刚的函数引用只有区区一行,这一行完全可以使用匿名方法实现,如果使用匿名方法的话就可以免去编写一个函数,代码显得非常简洁。
匿名方法使用方法也很简单。
委托类型 委托变量 = delegate (【参数列表】){代码块};
while (true) { //实例化一个委托变量,使用匿名方法构造 ProcessDelegate showProcess = delegate() { label1.Text = "当前时间 " + DateTime.Now.ToString(); }; label1.Invoke(showProcess); //线程暂停 Thread.Sleep(1000); }
方法三,使用MethodInvoker
再观察一下上面的代码,这个委托类型,输入参数无输出参数也无,就可以使用C#的MethodInvoker直接构造,关于MethodInvoker,MSDN给出这样一个解释“表示一个委托,该委托可执行托管代码中声明为 void 且不接受任何参数的任何方法”
//使用匿名方法2 while (true) { label1.Invoke ( //委托,托管无参数的任何方法 new MethodInvoker ( delegate { label1.Text = "当前时间 " + DateTime.Now.ToString(); } ) ); //线程暂停 Thread.Sleep(1000); }