A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 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的方式实现安全调用
&nbsp;&nbsp;
  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>&nbsp;&nbsp;&nbsp;&nbsp;    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



评分

参与人数 1技术分 +1 收起 理由
杞文明 + 1

查看全部评分

1 个回复

倒序浏览
值得学习ing!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马