本帖最后由 jerviscui 于 2013-6-25 22:39 编辑
有如下代码,在新建的线程中调用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; 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)
{</P><P> 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
|