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 }