当前位置: 首页 > news >正文

浅述WinForm多线程编程与Control.Invoke的应用

VS2008、C#3.0
在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来。一个最直接的方法便是使用多线程。多线程编程的方式在WinForm开发中必不可少。
本文介绍在WinForm开发中如何使用多线程,以及在线程中如何通过Control.Invoke方法返回窗体主线程执行相关操作。

-. WinForm多线程编程
1. new Thread()

    新开一个线程,执行一个方法,没有参数传递:
    

private void DoWork()  {
            Thread t = new Thread(new ThreadStart(this.DoSomething));
            t.Start();
        }
        private void DoSomething() {
            MessageBox.Show("thread start");
        }


    新开一个线程,执行一个方法,并传递参数:
    

private void DoWork()  {
            Thread t = new Thread(new ParameterizedThreadStart(this.DoSomething));
            t.Start("guozhijian");
        }
        private void DoSomething(object o) {
            MessageBox.Show(o.ToString());
        }

    参数定义为object类型。
2. ThreadPool
    众所周知,新开一个线程代价是很高昂的,如果我们每个操作都新开一个线程,那么太浪费了,于是,下面使用线程池。
    无参数传递:
    

private void DoWork()  {
            ThreadPool.QueueUserWorkItem(new WaitCallback(this.DoSomething));
        }
        private void DoSomething(object o) {
            MessageBox.Show("thread start");
        }

    有参数传递:
    

private void DoWork()  {
            ThreadPool.QueueUserWorkItem(new WaitCallback(this.DoSomething), "guozhijian");
        }
        private void DoSomething(object o) {
            MessageBox.Show(o.ToString());
        }

    使用匿名方法更灵活:
    

private void DoWork()  {
            string name = "guozhijian";
            ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object o){
                MessageBox.Show(name);
            }));
        }

    在匿名代码段里面可以直接访问局部变量,不用在关心参数传递的问题
二. Invoke
1. this.Invoke
现在,在业务线程里面执行完毕,要改变窗体控件的值了,此时,如果直接通过this得到控件的句柄,然后对它进行操作是会抛异常的,.Net WinForm Application里面是不允许这样的操作的。这是,可以调用Invoke方法

2.Invoke方法签名:
object Control.Invoke(Delegate Method)
object Control.Invoke(Delegate Method, params object[] args)

3.使用自定义委托

private void DoWork()  {
            WaitCallback wc = new WaitCallback(this.DoSomething);
            ThreadPool.QueueUserWorkItem(wc, "Guozhijian");
        }

        private delegate void MyInvokeDelegate(string name);
        private void DoSomething(object o) {
            this.Invoke(new MyInvokeDelegate(this.ChangeText), o.ToString());
        }

        private void ChangeText(string name) {
            this.textBox1.Text = name;
        }

哦,太麻烦了,难道我每次都要定义一个委托啊,这样可不行。

4.使用System.Action:

private void DoWork()  {
            WaitCallback wc = new WaitCallback(this.DoSomething);
            ThreadPool.QueueUserWorkItem(wc, "Guozhijian");
        }

        private void DoSomething(object o) {
            this.Invoke(new Action<string>(this.ChangeText), o.ToString());
        }

        private void ChangeText(string name) {
            this.textBox1.Text = name;
        }

本例传递一个参数,System.Action有很多个重载,可以无参数(非泛型),而最多可以有四个参数,同样采用匿名方法,不使用泛型形式的System.Action,如下:

private void DoWork()  {
            WaitCallback wc = new WaitCallback(this.DoSomething);
            ThreadPool.QueueUserWorkItem(wc, "Guozhijian");
        }

        private void DoSomething(object o) {
            this.Invoke(new Action(delegate() {
                this.textBox1.Text = o.ToString();
            }));
        }


5.使用System.Func
如果Invoke调用主窗体操作之后,还希望在调用完得到一个返回值:

private void DoWork()  {
            WaitCallback wc = new WaitCallback(this.DoSomething);
            ThreadPool.QueueUserWorkItem(wc, "Guozhijian");
        }

        private void DoSomething(object o) {
            System.Func<string, int> f = new Func<string, int>(this.GetId);
            object result = this.Invoke(f,o.ToString());
            MessageBox.Show(result.ToString());
        }

        private int GetId(string name) {
            this.textBox1.Text = name;
            if (name == "Guozhijian") {
                return 999;
            }
            else {
                return 0;
            }
        }


result的值为 999。
System.Func同样有很多泛形重载,这里不赘述。

6.关于Invoke的拥有者:Control
本文例中都是用this来引用,这里this替换为窗体任何一个控件的句柄都是OK的,因为Control.Invoke含义是将方法委托给拥有该Control的线程去执行。

转载于:https://www.cnblogs.com/netserver/p/5774995.html

相关文章:

  • 容器和泛型
  • 在Java中、、三者的区别
  • maven 安装本地jar包到本地maven仓库
  • 网络爬虫: 从allitebooks.com抓取书籍信息并从amazon.com抓取价格(3): 抓取amazon.com价格...
  • 河南多校联合训练 F 不是匹配
  • JAVA缓存技术
  • SAP PP 生产订单变更记录保存
  • 目标确定
  • spoj1812-Longest Common Substring II(后缀自动机)
  • 数据分析,了解行业
  • 加速ssh连接
  • nodeJS实战:自定义模块与引入,不同模块的函数传递及回调处理,exports与module.exports(基于nodejs6.2.0)...
  • Tweak 中系统方法写入文件到根目录下面失败
  • 在练习过程中遇到的几点小问题---关于布局
  • 附6 hystrix metrics and monitor
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • CSS进阶篇--用CSS开启硬件加速来提高网站性能
  • JavaScript-Array类型
  • java正则表式的使用
  • js对象的深浅拷贝
  • js正则,这点儿就够用了
  • leetcode讲解--894. All Possible Full Binary Trees
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • Redis 中的布隆过滤器
  • Sublime text 3 3103 注册码
  • Web Storage相关
  • 对象引论
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 开放才能进步!Angular和Wijmo一起走过的日子
  • 如何编写一个可升级的智能合约
  • 听说你叫Java(二)–Servlet请求
  • 推荐一款sublime text 3 支持JSX和es201x 代码格式化的插件
  • 新手搭建网站的主要流程
  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • 译米田引理
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​什么是bug?bug的源头在哪里?
  • ### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTr
  • (07)Hive——窗口函数详解
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (附源码)ssm跨平台教学系统 毕业设计 280843
  • (三)mysql_MYSQL(三)
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (原創) 如何讓IE7按第二次Ctrl + Tab時,回到原來的索引標籤? (Web) (IE) (OS) (Windows)...
  • *++p:p先自+,然后*p,最终为3 ++*p:先*p,即arr[0]=1,然后再++,最终为2 *p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
  • .net 程序发生了一个不可捕获的异常
  • .Net各种迷惑命名解释
  • ?.的用法
  • ??如何把JavaScript脚本中的参数传到java代码段中
  • @ModelAttribute使用详解
  • @Query中countQuery的介绍
  • @staticmethod和@classmethod的作用与区别
  • @SuppressLint(NewApi)和@TargetApi()的区别
  • [AMQP Connection 127.0.0.1:5672] An unexpected connection driver error occured
  • [Angular] 笔记 6:ngStyle