苏飞论坛

标题: 跨线程访问Windows控件 [打印本页]

作者: 印醒    时间: 2013-3-25 10:24
标题: 跨线程访问Windows控件
本帖最后由 印醒 于 2013-3-25 14:33 编辑

有时我们需要在某个Windows控件的非创建线程中访问它,下面是我在网上学习到的一个方法,挺好用的,来与大家分享一下,此处我以访问TextBox为例。
首先,在主线程中加入这样的一段代码
  1. //创建一个委托,是为访问TextBox控件服务的。
  2.         public delegate void UpdateTxt(string msg);
  3.         //定义一个委托变量
  4.         public UpdateTxt updateTxt;

  5.         //修改TextBox值的方法。
  6.         public void UpdateTxtMethod(string msg)
  7.         {
  8.                  this.txt.Text=msg;
  9.         }
  10.         //此为在非创建线程中的调用方法,其实是使用TextBox的Invoke方法。
  11.         public void ThreadMethodTxt(string msg)
  12.         {
  13.             this.txt.Invoke(updateTxt, new object[] { msg });
  14.         }
复制代码
然后,需要在页面加载时,将方法UpdateTxtMethod绑定绑定在updateTxt委托上
  1. updateTxt=this.UpdateTxtMethod;
复制代码
最后,在需要跨线程访问的地方调用ThreadMethodTxt(string msg)方法即可。

呵呵,在下知识有限,不能为大家解释这些代码,实在惭愧,还请高手,能补充一下
作者: 站长苏飞    时间: 2013-3-25 14:08
http://www.sufeinet.com/thread-13-1-1.html其实我的例子里有关于这块的使用,只是没有单独放出来。

线程与线程之间是不能直接通信 的,当然使用委托就不一样了。
这是典型的使用委托访问控件。
在子线程不能直接访问其它线程创建的控件变量,或者是直接变量。要想访问最好的办法就是使用这个委托

[code=csharp]   
             //创建一个委托,是为访问TextBox控件服务的。
            public delegate void UpdateTxt(string msg);
            //定义一个委托变量
            public UpdateTxtReceive updateTxt;

            //修改TextBox值的方法。
            public void UpdateTxtMethod(string msg)
            {
                     this.txt.Text=msg;
            }
            //此为在非创建线程中的调用方法,其实是使用TextBox的Invoke方法。
            public void ThreadMethodTxt(string msg)
            {
                this.txt.Invoke(updateTxtReceive, new object[] { msg });
            }[/code]
其实楼主在使用时加载这部分可以这样写
[code=csharp]updateTxt=new UpdateTxtReceive(UpdateTxtMethod)[/code]
这样就行了,
而 this.txt.Invoke(updateTxtReceive, new object[] { msg });同样也可以修改为
[code=csharp] this.txt.Invoke(updateTxtReceive, msg );[/code]
或者是[code=csharp]updateTxtReceive(msg)[/code]
不过也不知道什么原因楼主的代码可能存在一个小问题那就是 你定义的委托实例为updateTxt而你一直使用的是updateTxtReceive,还有UpdateTxtReceive 委托从来没有出现过,楼主定义的是UpdateTxt而下面怎么出现updateTxtReceive呢?如果只是这样是没有办法实现楼主所说的效果的,
我修改如下
所代码应该修改为如下所示
[code=csharp]  //创建一个委托,是为访问TextBox控件服务的。
        public delegate void UpdateTxt(string msg);
        //定义一个委托变量
        public UpdateTxt updateTxt;

        private void Form1_Load(object sender, EventArgs e)
        {
            updateTxt = new UpdateTxt(UpdateTxtMethod);
        }
        //修改TextBox值的方法。
        public void UpdateTxtMethod(string msg)
        {
            this.txt.Text = msg;
        }
        //此为在非创建线程中的调用方法,其实是使用TextBox的Invoke方法。
        public void ThreadMethodTxt(string msg)
        {
            this.txt.Invoke(UpdateTxt, new object[] { msg });
            //以下是苏飞修改部分
            //this.txt.Invoke(updateTxt, new object[] { msg });
            //updateTxt(msg)
            //如果是窗体的可以这样写
            //  this.BeginInvoke(updateTxt, msg);
        }
[/code]
这样就可以实例了,
关键这块的可以参考一下我上面发的例子,或者是参考一下这个
http://www.sufeinet.com/forum.php?mod=viewthread&tid=2153

作者: 印醒    时间: 2013-3-25 14:31
站长苏飞 发表于 2013-3-25 14:08
http://www.sufeinet.com/thread-13-1-1.html其实我的例子里有关于这块的使用,只是没有单独放出来。

线 ...

不好意思啊,这块是我做的一个项目中的代码,updateTxtReceive是我的原变量名,发帖时把Receive去掉了。为了说清问题把变量名改了,那个应该是忘记改的,谢谢飞哥的完善,我把这块拉出来只是希望能够方便那些需要这块知识的朋友,多谢飞哥,这下大家就能看懂了
作者: 站长苏飞    时间: 2013-3-25 14:35
印醒 发表于 2013-3-25 14:31
不好意思啊,这块是我做的一个项目中的代码,updateTxtReceive是我的原变量名,发帖时把Receive去掉了。 ...

呵呵,我只是简单修改下,其实你的代码已经表示出来意思了,只是删除时没有删除干净,仍然很感谢你的分享
作者: 印醒    时间: 2013-3-25 14:36
站长苏飞 发表于 2013-3-25 14:35
呵呵,我只是简单修改下,其实你的代码已经表示出来意思了,只是删除时没有删除干净,仍然很感谢你的分享

飞哥,为什么我发表的代码中的注释部分是灰色的,而不是绿色的呢?
作者: 站长苏飞    时间: 2013-3-25 14:37
印醒 发表于 2013-3-25 14:36
飞哥,为什么我发表的代码中的注释部分是灰色的,而不是绿色的呢?

http://www.sufeinet.com/thread-1942-1-1.html
作者: 秋日的枫叶    时间: 2013-6-3 17:17
你说的方法很好,说心里话,菜鸟还是不太懂委托。 苏飞给的也没怎么看懂。 我网上找了个刷新窗体的办法,蛮好的,给大家参考下 Application.DoEvents(); 增加这句代码就可以了
作者: 站长苏飞    时间: 2013-6-3 17:24
秋日的枫叶 发表于 2013-6-3 17:17
你说的方法很好,说心里话,菜鸟还是不太懂委托。 苏飞给的也没怎么看懂。 我网上找了个刷新窗体的办法,蛮 ...

你这个治标不治本,使用线程,不仅仅是为了刷新,更重的是性能问题,委托是为了访问,而不是为了刷新窗体。显示在窗体上只是为了查阅方便,但是访问还是需要的,

线程解决性能,委托解决访问
作者: 秋日的枫叶    时间: 2013-6-3 17:27
恩,谢谢苏大
今天晚上回去就研读多线程和委托
作者: 秋日的枫叶    时间: 2013-6-3 23:07
看了,没懂。
过几天再重看
作者: 神同步    时间: 2015-7-22 21:17
其实还可以这样

this.Invoke(new Action(() =>
                   {
                     txt.Text="赋值";
                   }));
作者: 小哲    时间: 2016-10-7 15:28
Control.CheckForIllegalCrossThreadCalls = false;//忽略跨线程间的调用.不推荐大家使用.它可能会引发一些未知的异常.






欢迎光临 苏飞论坛 (http://www.sufeinet.com/) Powered by Discuz! X3.4