C#中的invoke方法

在用.NET Framework框架的WinForm构建GUI程序界面时,如果要在控件的事件响应函数中改变控件的状态,例如:某个按钮上的文本原先叫“打开”,单击之后按钮上的文本显示“关闭”,初学者往往会想当然地这么写:

void ButtonOnClick(object sender,EventArgs e)

{

button.Text="关闭";

}

这样的写法运行程序之后,可能会触发异常,异常信息大致是“不能从不是创建该控件的线程调用它”。注意这里是“可能”,并不一定会触发该种异常。造成这种异常的原因在于,控件是在主线程中创建的(比如this.Controls.Add(...);),进入控件的事件响应函数时,是在控件所在的线程,并不是主线程。在控件的事件响应函数中改变控件的状态,可能与主线程发生线程冲突。如果主线程正在重绘控件外观,此时在别的线程改变控件外观,就会造成画面混乱。不过这样的情况并不总会发生,如果主线程此时在重绘别的控件,就可能逃过一劫,这样的写法可以正常通过,没有触发异常。

正确的写法是在控件响应函数中调用控件的Invoke方法(其实如果大家以前用过C++ Builder的话,也会找到类似Invoke那样的激活到主线程的函数)。Invoke方法会顺着控件树向上搜索,直到找到创建控件的那个线程(通常是主线程),然后进入那个线程改变控件的外观,确保不发生线程冲突。正确写法的示例如下:

void ButtonOnClick(object sender,EventArgs e)

{

button.Invoke(new EventHandler(delegate

{

button.Text="关闭";

}));

}

Invoke方法需要创建一个委托。你可以事先写好函数和与之对应的委托。不过,若想直观地在Invoke方法调用的时候就看到具体的函数,而不是到别处搜寻的话,上面的示例代码是不错的选择。

这样的写法有一个烦人的地方:对不同的控件写法不同。对于TextBox,要TextBoxObject.Invoke,对于Label,又要LabelObject.Invoke。有没有统一一点的写法呢?

主窗口类本身也有Invoke方法。如果你不想对不同的控件写法不一样,可以全部用this.Invoke:

void ButtonOnClick(object sender,EventArgs e)

{

this.Invoke(new EventHandler(delegate

{

button.Text="关闭";

}));

}

在C# 3.0及以后的版本中有了Lamda表达式,像上面这种匿名委托有了更简洁的写法。.NET Framework 3.5及以后版本更能用Action封装方法。例如以下写法可以看上去非常简洁:

void ButtonOnClick(object sender,EventArgs e)

{

this.Invoke(new Action(()=>

{

button.Text="关闭";

}));

}

以上写法往往充斥着WinForm构建的程序。

在微软新一代的界面开发技术WPF中,由于界面呈现和业务逻辑原生态地分开在两个线程中,所以控件的事件响应函数就不必Invoke了。但是,如果手动开辟一个新线程,那么在这个新线程中改变控件的外观,则还是要Invoke的。

C#中的invoke方法相关推荐

  1. InvocationHandler实现类中的invoke方法为什么会被自动执行

    一:首先需要明确的是动态代理中,InvocationHandler实现类并不是代理类,只是代理类与被代理类的一个中间类,该类只是用来做功能增强的,这也是动态代理能够解耦的原因 二:动态代理中的代理类是 ...

  2. java中的invoke方法_详解Java中Method的Invoke方法

    在写代码的时候,发现从父类class通过getDeclaredMethod获取的Method可以调用子类的对象,而子类改写了这个方法,从子类class通过getDeclaredMethod也能获取到M ...

  3. java反射中method类中的invoke方法是做什么的,他有什么作用?

    就是调用类中的方法,最简单的用法是可以把方法参数化 invoke(class, method) 比如你Test类里有一系列名字相似的方法setValue1.setValue2等等 可以把方法名存进数组 ...

  4. Java动态代理invoke方法自动执行的原因

    Java动态代理invoke方法自动执行的原因 在动态代理中,一般的是先调用Proxy.newProxyInstance()生成代理对象,然后通过调用代理对象的对应方法来实现增强,这里假设代理了被代理 ...

  5. InvocationHandle的invoke方法

    在学习代理模式中接触到了动态代理的相关内容,这是AOP的核心内容.先用一个例子说明 动态代理 的使用 //接口(动态代理只能代理接口) public interface Subject { publi ...

  6. jdk动态代理invoke方法自动运行原因

    invoke 方法介绍 想要知道 invoke方法为什么会自动调用我们先要来了解一下这个方法 public interface InvocationHandler { public Object in ...

  7. Method的invoke方法初步了解

    Java调试过程中,我们有时候会需要对JVM运行过程中哪出了问题进行调试,先从最基础的了解. 我们都知道Java框架中方法的调用基本上都是通过反射机制来实施的,具体流程如下: 1.方法的调用先检查Ac ...

  8. 动态代理模式newProxyInstance及invoke方法参数详解

    动态代理概述: Java提供的动态代理类Proxy: Proxy provides static methods for creating dynamic proxy classes and inst ...

  9. 第九节:深究并行编程Parallel类中的三大方法 (For、ForEach、Invoke)和几大编程模型(SPM、APM、EAP、TAP)

    一. 并行编程 1. 区分串行编程和串行编程 ①. 串行编程:所谓的串行编程就是单线程的作用下,按顺序执行.(典型代表for循环 下面例子从1-100按顺序执行) ②. 并行编程:充分利用多核cpu的 ...

最新文章

  1. 几道常见String面试题
  2. 解决xcode ***is missing from working copy
  3. mysql报错 Incorrect table definition;there can be only one auto column and it must be defined as a key
  4. f_bfree和f_bavail的区别
  5. IDEA中Maven项目创建单元测试(JUnit4)
  6. oracle雾化试图_Oracle 物化视图 说明
  7. 线性表的C/C++实现(数据结构 严蔚敏版)
  8. ef6 mysql_VS2015 + EF6连接MYSQL5.6
  9. 推荐一些vue.js热门好用的框架组件
  10. ios 添加条纹背景
  11. R语言正则表达式[stringr package]
  12. 新手玩荔枝派 f1c100s nano折腾笔记(四)
  13. 移动安全-IOS越狱
  14. 异常检测时间序列_神经病学时间序列/异常检测:分层时间记忆
  15. 关于碰到优盘插入电脑检测到病毒并且优盘里文件只显示System Volume Information文件夹的问题解决。
  16. 在java中 以下关于集合框架_在Java中LinkedList类和ArrayList类同属于集合框架类,下列...
  17. 帆软FineReport8.0使用技巧总结及常见问题解决
  18. MySQL 日期字符串转换
  19. warning: LF will be replaced by CRLF in bispython/venv/Lib/site-packages/dja
  20. 伪类选择器和伪元素选择器

热门文章

  1. SCOI2015 小凸玩密室
  2. Linux操作指导专题
  3. CountDown原理及使用
  4. 为mongoDB数据库添加账号步骤
  5. WPF 分散对齐TextBlock
  6. 计算机算法的概念教案,1.1.1 算法的概念公开课教案(教学设计)
  7. YGG SEA——首个 YGG 区域 subDAO介绍
  8. jax-ws java_通过JAX-WS实现WebService
  9. 杰理之Wi-Fi阶段【篇】
  10. 前端转安卓开发!作为一名程序员我不忘初心,进阶学习资料!