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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© mdb 中级黑马   /  2014-3-18 00:20  /  1890 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 mdb 于 2014-3-22 16:51 编辑

我们知道,当在一个新的线程里操作主线程上的控件时,会引发类似于“线程间操作无效: 从不是创建控件“textBox1”的线程访问它”的异常,当然我们可以在窗体的构造方法里设置CheckForIllegalCrossThreadCalls=false即可让程序不报这个异常提示。
修改CheckForIllegalCrossThreadCalls的属性会有什么副作用吗,如果不修改CheckForIllegalCrossThreadCalls属性,还有什么方法能让程序不引发线程间操作无效的异常?

评分

参与人数 1技术分 +1 收起 理由
czwanglei + 1

查看全部评分

3 个回复

倒序浏览
求涨姿势~~
回复 使用道具 举报
CheckForIllegalCrossThreadCalls是Control的静态类,定义如下:

public static bool CheckForIllegalCrossThreadCalls { get; set; }

因此可以这么用:Control.CheckForIllegalCrossThreadCalls,又因为Form继承自Control,所以可以直接调用这个属性,一旦这个属性设置为False,所有控件都会共享这个属性
回复 使用道具 举报
        在WinForm或WPF中,默认只允许在创建控件的线程(一般为UI线程)中访问控件,如果我们想在子线程中访问UI线程的资源,需要做特殊处理
        WinForm处理方式
WinForm当中,我们有两种方式来解决这个问题。我们可以在窗体构造函数当中添加CheckForIllegalCrossThreadCalls = false,禁止窗体进行非法跨线程调用的校验,只是屏蔽了非法校验,并没有真正解决问题,不推荐使用
我们可以使用一下方式解决WinForm中UI资源的跨线程调用问题
        private void button1_Click(object sender, EventArgs e)
        {
            Thread thread = new Thread(() => ChangeText());
            thread.Start();
        }
        private void ChangeText()
        {
            Random rdm = new Random();
            string num = rdm.Next().ToString();
            //当前线程是创建此控件的线程
            if (txt.InvokeRequired)
                txt.Invoke(new Action<string>(s => txt.Text = s), num);
            //当前线程不是创建此控件的线程
            else
                txt.Text = num;
        }
        WPF程序的处理方式
每个WPF应用程序中都有一个Dispatcher类对象,该类对象是一个队列,用来保存应用程序主线程中的所有正在执行的工作。为了避免多个线程通过访问同一WPF控件的相同属性,其他线程应该请求主线程代表它执行访问控件属性的操作,即把访问主线程的方法放到主线程的Dispather类的对象中排队
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Thread thread = new Thread(() => ChangeText());
            thread.Start();
        }
        private void ChangeText()
        {
            Random rdm = new Random();
            string num = rdm.Next().ToString();
            //当前线程不是主线程
            if (Dispatcher.Thread != Thread.CurrentThread)
            {
                Dispatcher.Invoke(new Action<string>(s => txt.Text = s), num);
            }
            //当前线程是主线程
            else
                txt.Text = num;
        }
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马