关于线程间操作无效: 从不是创建控件“xx”的线程访问它,错误解决方法(自定义委托和系统委托Action或Func解决)

这是一个线程不安全的问题。跨线程操作问题。

比如我们需要在线程中改变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         }

 

posted on 2015-08-13 11:01  凝冰  阅读(370)  评论(0编辑  收藏  举报