这是一个线程不安全的问题。跨线程操作问题。
比如我们需要在线程中改变textbox的文本,textbox的name是txtShowMsg
第一种方法(不推荐使用)
在窗体构造函数中写Control.CheckForIllegalCrossThreadCalls =false;
这种方法,只是不去检查跨线程的安全性。
第二种方法(推荐使用)
第一步:定义一个委托
/// <summary> /// 委托改变 Text的值 /// </summary> /// <param name="TextBox">文本框控件</param> /// <param name="string">需要改变的值</param> /// <returns></returns> delegate void SetTextBoxMsgDel(TextBox txt,string num);
第二步:创建改变text值的方法
/// <summary> /// 改变控件的值 /// </summary> /// <param name="txt">文本框控件</param> /// <param name="msg">需要改变的值</param> private void SetTextMgs(TextBox txt, string msg) { //判断控件是否在使用 if (txt.InvokeRequired) { //在使用用委托调用自己 SetTextBoxMsgDel stbd = SetTextMgs; Invoke(stbd, new object[] { txt, msg }); } else { //没在使用去改变 txt.Text = msg; } }
第三步:在线程中调用SetTextMsg方法
总结,跨线程改变控件属性的时候,需要控件在没有使用的时候再去改变,如果两个地方都在使用,不能确定那个地方是对的了。
所以,需要在别的线程没有使用该控件的时候去改变控件属性。
方法三:使用泛型委托 Action、Func
将方法二中的委托定义省略。使用系统定义好的泛型委托。
1 /// <summary> 2 /// 改变控件的值 3 /// </summary> 4 /// <param name="txt">文本框控件</param> 5 /// <param name="msg">需要改变的值</param> 6 private void SetTextMgs(TextBox txt, string msg) 7 { 8 //判断控件是否在使用 9 if (txt.InvokeRequired) 10 { 11 //在使用用委托调用自己 12 Action<TextBox,string> stbd = SetTextMgs; 13 Invoke(stbd, new object[] { txt, msg }); 14 } 15 else 16 { 17 //没在使用去改变 18 txt.Text = msg; 19 } 20 }