-
线程调用控件过程中出现了异常?
有如下代码,在新建的线程中调用textBox的方法时候,调试器报出异常。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Net.Sockets; using System.Net; using System.Threading; namespace _01_socketclient { public partial class SocketClient : Form { Thread receiveThread = null; //接受线程 public SocketClient() { InitializeComponent(); } private void btnConnection_Click(object sender, EventArgs e) { //实例接收线程 receiveThread = new Thread(new ThreadStart(RecevieThread)); //设置为后台线程 receiveThread.IsBackground = true; //启动接受线程 receiveThread.Start(); } /// <summary> /// 显示文本信息 /// </summary> /// <param name="msg"></param> private void ShowMsg(string msg) { txtShow.AppendText(msg + "\r\n"); } /// <summary> /// 接收线程执行方法 /// </summary> private void RecevieThread() { string strMsg = "hello world" ShowMsg(strMsg); } } }
-
为什么会出现这中情况呢?
原来是线程非安全方式访问控件。就是说,如果创建某控件的线程之外的其他线程试图调用该控件,则调试器会引发一个 InvalidOperationException,并提示消息:“从不是创建控件 control name 的线程访问它。”
-
那这种情况该如何处理呢?
可以通过将 CheckForIllegalCrossThreadCalls 属性的值设置为 false 来禁用此异常。
MSDN中提到了通过控件的 InvokeRequired 属性来判断调用控件的是哪一个线程,如果是非安全线程调用空间则使用实际调用空间的委托来调用Invoke。
Invoke(Delegate, array< Object[]()>[] ) 该方法的作用:在拥有此控件的基础窗口句柄的线程上执行指定的委托。
-
我是这样做的
1.查询控件的 InvokeRequired 属性。
2.如果 InvokeRequired 返回true,则使用实际调用控件的委托来调用Invoke。
3.如果 InvokeRequired 返回false,则直接调用控件。
代码如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Net.Sockets; using System.Net; using System.Threading; namespace _01_socketclient { public partial class SocketClient : Form { Thread receiveThread = null; //接受线程 delegate void SetTextCallback(string text);//invoke的方式实现安全调用 public SocketClient() { InitializeComponent(); } private void btnConnection_Click(object sender, EventArgs e) { //实例接收线程 receiveThread = new Thread(new ThreadStart(RecevieThread)); //设置为后台线程 receiveThread.IsBackground = true; //启动接受线程 receiveThread.Start(); } /// <summary> /// 显示文本信息 /// </summary> /// <param name="msg"></param> private void ShowMsg(string msg)
{ if (txtShow.InvokeRequired) {
SetTextCallback d = new SetTextCallback(ShowMsg); ; Invoke(d, new object[] { msg }); } else { txtShow.AppendText(msg + "\r\n"); } }
/// <summary> /// 接收线程执行方法 /// </summary> private void RecevieThread() { string strMsg = "hello world" ShowMsg(strMsg); } } }-The End-
© Jervis