winform线程间传值

最终达到的效果:

相信很多朋友做多线程的时候都遇到过..线程间操作无效:从不是创建控件"XXX"的线程访问他.

通过错误,可以了解到问题的原因.

简单的解决办法1:

取消线程安全检查,可以解决跨线程的访问.但不建议这么做

在窗体的构造函数中,或者onload中加上这句就好了

Control.CheckForIllegalCrossThreadCalls = false;

简单的解决办法2:

使用委托;

 

 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Data;
 5 using System.Drawing;
 6 using System.Linq;
 7 using System.Text;
 8 using System.Windows.Forms;
 9 using System.Threading;
10 
11 namespace 窗体间同步传值_单线程___使用委托
12 {
13     //定义委托
14     public delegate void Mydelegate(string str); 
15 
16      //
17     public partial class frmMain : Form
18     {        
19         //创建一个委托对象.供invoke调用,并在构造函数内赋值
20         Mydelegate InvokeDel;
21         public frmMain()
22         {
23             InitializeComponent();
24             this.Text = this.Text +"线程ID:"+ Thread.CurrentThread.ManagedThreadId;
25             //取消线程安全检查,可以解决跨线程的访问.但不建议这么做
26             //Control.CheckForIllegalCrossThreadCalls = false;
27             InvokeDel = new Mydelegate(setText);
28             //初始化了一个委托对象,setText这个方法的参数必须符合委托Mydelegate的参数类型
29         }
30 
31         private void btnNewFrm_Click(object sender, EventArgs e)
32         {
33             frmChild f = new frmChild();
34             f.mydel = setText;//新建窗体对象的时候,把方法传递给新窗体的委托对象.
35             f.Show();
36         }
37         private void setText(string txt)
38         {
39             //InvokeRequired,当线程执行到此时,校验当前控件txtmsg哪个线程创建的.
40             //如果是自己创建的,返回false,如果不是自己创建的返回true
41             if (this.txtmsg.InvokeRequired)
42             {   //当该控件不是自己创建的,如果直接赋值将会出现跨线程访问的问题
43                 //这里调用Invoke方法.参数是一个InvokeDel委托,txt是该委托对应的方法的参数
44                 this.Invoke(InvokeDel, txt);
45             }
46             else {
47                 this.txtmsg.Text = txt;
48             }            
49         }
50         private void btnNewThread_Click(object sender, EventArgs e)
51         {
52             //注意:调用的方法带参数时候的 参数一定要是object类型,且只能有一个
53            // Thread td = new Thread(new ParameterizedThreadStart(这里写方法名,参数为Object,只能一个参数));
54            // Thread td = new Thread(showChildFrm);简单写法
55             Thread td = new Thread(() => {//使用lambda表达式无参数可以用()代替
56                                             frmChild f = new frmChild();
57                                             f.mydel = setText;//为子窗体的委托对象赋值(一个方法.)
58                                             f.ShowDialog();            
59                                         });
60             td.Start();
61             //线程中的调用如果有参数(例如:frmChild这个窗体,调用构造函数时需要一个参数的,可以td.start(参数)),
62 
63         }
64         //public void showChildFrm(object obj)
65         //{
66         //    frmChild f = new frmChild();
67         //    f.mydel = setText;
68         //    //使用线程打开新窗体的时候,要使用ShowDialog
69         //    f.ShowDialog();
70         //}
71     }
72 }
主窗体

 

 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Data;
 5 using System.Drawing;
 6 using System.Linq;
 7 using System.Text;
 8 using System.Windows.Forms;
 9 using System.Threading;
10 
11 namespace 窗体间同步传值_单线程___使用委托
12 {
13     public partial class frmChild : Form
14     {
15         //创建一个实例委托对象,此时该对象为空.由调用者传入该值.
16        public Mydelegate mydel;
17         public frmChild()
18         {
19             InitializeComponent();
20             this.Text = this.Text + "线程ID:" + Thread.CurrentThread.ManagedThreadId;
21         }
22 
23 
24         private void btnSend_Click(object sender, EventArgs e)
25         {
26             if (mydel!=null)
27             {
28                 mydel.Invoke(txtSTR.Text);
29                 //或者
30                 //mydel(txtSTR.Text);
31             }
32         }
33     }
34 }
子窗体

 

 

posted on 2013-07-31 15:52  toward fai  阅读(619)  评论(0)    收藏  举报