有如下代码,在新建的线程中调用textBox的方法时候,调试器报出异常。
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;
-The End-
© Jervis
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) | 黑马程序员IT技术论坛 X3.2 |