• 委托的前世今生


    -Begin-

    起因

    很多C#初学者,都遇到过这样的问题——线程间操作无效,从不是创建控件的线程访问它。

    今天就这个问题,展开分析。

    溯源

    先说下这个问题产生的根源。

    大家都知道,程序运行起来之后,首先会有一个主线程,主线程用于处理控件生成、界面渲染、事件响应、逻辑处理等操作,因此我们可以理解为窗体里的控件是属于主线程的。

    我们也知道多线程,如果我们想实现与主线程同时执行另一件事,一般会去使用多线程。

    因此多线程,从某种意义上来说,它和主线程都属于“线程”这个家族,他们的身份是“平等”的,就像你和你同事之间的关系一样。

    那么,试想一下,如果你同事有一天想从你手上把你的PLC或者上位机项目程序拿过去,你愿不愿意?

     所以,如果在多线程里操作主线程的控件,你觉得主线程会不会答应,当然不会,主线程不答应的最直接表现就是,它会直接给一个报错,权当警告,如下图所示:

    解决

    那么如何解决呢?

    你的同事如果非要拿到你的程序,他会想,硬的不行,就来软的。

    所以他会找到你们共同的领导,跟你们领导这样说:“我手头上的这个100万的项目,能给公司带来50%的利润,现在需要用到他之前那个项目里的一个小知识,需要他把程序给我参考一下”。

    在公司利益面前,你觉得你的领导会怎么办?

    于是,领导和你“商量”了一下,毋庸置疑,你妥协了。

    你的同事使用的招数叫做——委托。

    那么,现在回到之前的问题上来,现在多线程要操作主线程的控件,是不是也可以使用委托来实现?

    前世

    委托定义:委托(Delegate) 是对某个方法的引用的一种引用类型变量。

    如果这句话看不懂,那就别看了,跟着我动手做。

    1、声明委托

    委托声明需要根据执行的方法来定,严格来说,就是根据执行方法的返回值和参数,我们只是给窗体的Text设置一个固定值而已,因此我们的参数是空,返回值也为空。

    声明委托如下:

    2、创建委托对象

    委托严格来说是一种类型,就像类一样,如果想要调用某个类,必须要创建一个该类的对象,所以我们要创建一个委托对象:

    3、创建委托方法

    委托对象也只是一个对象而已,就像领导一样,领导是不可能干活的,最终干活还得靠底下的兵来干,所以我们还得招人去干活。

    招人干活就是委托方法,我们现在这个活很简单,所以我们的方法也很简单。

    4、委托绑定

    我们招到了一个“兵”,现在也有一个部门领导,怎么把他们联系起来呢?

    很简单,让人事把这个兵分到这个部门就行了,这个分配的过程就是委托绑定,代码如下:

    5、委托调用

    万事俱备,只欠东风,终于干活了。

    作为公司的老板,一般是不可能跟员工打交道的,他会把任务分配给部门领导,部门领导会把活再分配下去,所以我们委托调用,也是调用委托对象。

    以上五步,就是委托的实现过程。

    然而,我们运行之后,还是会报错。

    没有那么简单的事!

    因为想要在多线程里操作主线程的控件,你还得经过控件的同意,怎么经过控件同意呢?

    控件的父类Control提供了一个这样的方法:

     意思就是说,想要操作控件,必须要通过Invoke方法来实现,Invoke方法里参数是一个委托,于是,我们只能灰溜溜地,这样写:

     果然,按照规矩来,就能达到效果:

    今生

    微软从某个版本开始,出来了Action和Lamda表达式,Action是系统委托,也就是说,不需要我们手动创建委托了,它有个兄弟叫Func,Action没有返回值,最多可以有16个参数,Func必须要有返回值,最多可以有16个参数,最后一个参数表示返回值。

    于是我们开始简化:

    第一步简化:用Action作为委托来创建

     第二步简化:委托对象只用一次,所以可以直接放到参数里

     第三步简化:用Lamda表达式代替方法

    总结

    我们所以常写的那行代码,其实只是一种简写方式而已,委托的五步法,不管怎么简化,怎么优化,其实本质还是一样,都离开不了这五个步骤。

    这就是经典。

    都看到这里了,是不是要点个赞呢?

  • 相关阅读:
    linux如何安装django
    Flume报 Space for commit to queue couldn't be acquired. Sinks are likely not keeping up with sources, or the buffer size is too tight
    window下用notepad++编辑了脚本文件然后放在linux报错显示无法运行
    如何使用mysqldump备份数据库
    mysql基础小结
    复合序列分解预测实例
    互联网金融平台客户留存计算实例(月留存为例)
    互联网金融不同渠道评估实例
    互联网金融投资平台返现活动效果案例分析
    spark内核揭秘-07-DAGScheduler源码解读初体验
  • 原文地址:https://www.cnblogs.com/xiketang/p/15871678.html
Copyright © 2020-2023  润新知