黑马程序员技术交流社区

标题: 关于跨线程检查的问题 [打印本页]

作者: mdb    时间: 2014-3-18 00:20
标题: 关于跨线程检查的问题
本帖最后由 mdb 于 2014-3-22 16:51 编辑

我们知道,当在一个新的线程里操作主线程上的控件时,会引发类似于“线程间操作无效: 从不是创建控件“textBox1”的线程访问它”的异常,当然我们可以在窗体的构造方法里设置CheckForIllegalCrossThreadCalls=false即可让程序不报这个异常提示。
修改CheckForIllegalCrossThreadCalls的属性会有什么副作用吗,如果不修改CheckForIllegalCrossThreadCalls属性,还有什么方法能让程序不引发线程间操作无效的异常?
作者: cancle    时间: 2014-3-18 10:09
求涨姿势~~
作者: shangxin    时间: 2014-3-18 11:45
CheckForIllegalCrossThreadCalls是Control的静态类,定义如下:

public static bool CheckForIllegalCrossThreadCalls { get; set; }

因此可以这么用:Control.CheckForIllegalCrossThreadCalls,又因为Form继承自Control,所以可以直接调用这个属性,一旦这个属性设置为False,所有控件都会共享这个属性

作者: zhangcheng5468    时间: 2014-3-22 16:43
        在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;
        }





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2