http://www.sufeinet.com/plugin.php?id=keke_group

苏飞论坛

 找回密码
 马上注册

QQ登录

只需一步,快速开始

分布式系统框架(V2.0) 轻松承载百亿数据,千万流量!讨论专区 - 源码下载 - 官方教程

HttpHelper爬虫框架(V2.7-含.netcore) HttpHelper官方出品,爬虫框架讨论区 - 源码下载 - 在线测试和代码生成

HttpHelper爬虫类(V2.0) 开源的爬虫类,支持多种模式和属性 源码 - 代码生成器 - 讨论区 - 教程- 例子

查看: 28188|回复: 17

[Winform] 跨线程访问Windows控件

[复制链接]
发表于 2013-3-25 10:24:15 | 显示全部楼层 |阅读模式
本帖最后由 印醒 于 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)方法即可。

呵呵,在下知识有限,不能为大家解释这些代码,实在惭愧,还请高手,能补充一下

本帖被以下淘专辑推荐:



1. 开通SVIP会员,免费下载本站所有源码,不限次数据,不限时间
2. 加官方QQ群,加官方微信群获取更多资源和帮助
3. 找站长苏飞做网站、商城、CRM、小程序、App、爬虫相关、项目外包等点这里
发表于 2013-6-3 17:24:46 | 显示全部楼层
秋日的枫叶 发表于 2013-6-3 17:17
你说的方法很好,说心里话,菜鸟还是不太懂委托。 苏飞给的也没怎么看懂。 我网上找了个刷新窗体的办法,蛮 ...

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

线程解决性能,委托解决访问
发表于 2013-3-25 14:08:26 | 显示全部楼层
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:25 | 显示全部楼层
站长苏飞 发表于 2013-3-25 14:08
http://www.sufeinet.com/thread-13-1-1.html其实我的例子里有关于这块的使用,只是没有单独放出来。

线 ...

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

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

飞哥,为什么我发表的代码中的注释部分是灰色的,而不是绿色的呢?
发表于 2013-3-25 14:37:48 | 显示全部楼层
印醒 发表于 2013-3-25 14:36
飞哥,为什么我发表的代码中的注释部分是灰色的,而不是绿色的呢?

http://www.sufeinet.com/thread-1942-1-1.html
发表于 2013-6-3 17:17:45 | 显示全部楼层
你说的方法很好,说心里话,菜鸟还是不太懂委托。 苏飞给的也没怎么看懂。 我网上找了个刷新窗体的办法,蛮好的,给大家参考下 Application.DoEvents(); 增加这句代码就可以了
发表于 2013-6-3 17:27:32 | 显示全部楼层
恩,谢谢苏大
今天晚上回去就研读多线程和委托
发表于 2013-6-3 23:07:16 | 显示全部楼层
看了,没懂。
过几天再重看
您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

QQ|手机版|小黑屋|手机版|联系我们|关于我们|广告合作|苏飞论坛 ( 豫ICP备18043678号-2)

GMT+8, 2024-5-8 08:51

© 2014-2021

快速回复 返回顶部 返回列表