C#中的invoke方法
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方法相关推荐
- InvocationHandler实现类中的invoke方法为什么会被自动执行
一:首先需要明确的是动态代理中,InvocationHandler实现类并不是代理类,只是代理类与被代理类的一个中间类,该类只是用来做功能增强的,这也是动态代理能够解耦的原因 二:动态代理中的代理类是 ...
- java中的invoke方法_详解Java中Method的Invoke方法
在写代码的时候,发现从父类class通过getDeclaredMethod获取的Method可以调用子类的对象,而子类改写了这个方法,从子类class通过getDeclaredMethod也能获取到M ...
- java反射中method类中的invoke方法是做什么的,他有什么作用?
就是调用类中的方法,最简单的用法是可以把方法参数化 invoke(class, method) 比如你Test类里有一系列名字相似的方法setValue1.setValue2等等 可以把方法名存进数组 ...
- Java动态代理invoke方法自动执行的原因
Java动态代理invoke方法自动执行的原因 在动态代理中,一般的是先调用Proxy.newProxyInstance()生成代理对象,然后通过调用代理对象的对应方法来实现增强,这里假设代理了被代理 ...
- InvocationHandle的invoke方法
在学习代理模式中接触到了动态代理的相关内容,这是AOP的核心内容.先用一个例子说明 动态代理 的使用 //接口(动态代理只能代理接口) public interface Subject { publi ...
- jdk动态代理invoke方法自动运行原因
invoke 方法介绍 想要知道 invoke方法为什么会自动调用我们先要来了解一下这个方法 public interface InvocationHandler { public Object in ...
- Method的invoke方法初步了解
Java调试过程中,我们有时候会需要对JVM运行过程中哪出了问题进行调试,先从最基础的了解. 我们都知道Java框架中方法的调用基本上都是通过反射机制来实施的,具体流程如下: 1.方法的调用先检查Ac ...
- 动态代理模式newProxyInstance及invoke方法参数详解
动态代理概述: Java提供的动态代理类Proxy: Proxy provides static methods for creating dynamic proxy classes and inst ...
- 第九节:深究并行编程Parallel类中的三大方法 (For、ForEach、Invoke)和几大编程模型(SPM、APM、EAP、TAP)
一. 并行编程 1. 区分串行编程和串行编程 ①. 串行编程:所谓的串行编程就是单线程的作用下,按顺序执行.(典型代表for循环 下面例子从1-100按顺序执行) ②. 并行编程:充分利用多核cpu的 ...
最新文章
- 几道常见String面试题
- 解决xcode ***is missing from working copy
- mysql报错 Incorrect table definition;there can be only one auto column and it must be defined as a key
- f_bfree和f_bavail的区别
- IDEA中Maven项目创建单元测试(JUnit4)
- oracle雾化试图_Oracle 物化视图 说明
- 线性表的C/C++实现(数据结构 严蔚敏版)
- ef6 mysql_VS2015 + EF6连接MYSQL5.6
- 推荐一些vue.js热门好用的框架组件
- ios 添加条纹背景
- R语言正则表达式[stringr package]
- 新手玩荔枝派 f1c100s nano折腾笔记(四)
- 移动安全-IOS越狱
- 异常检测时间序列_神经病学时间序列/异常检测:分层时间记忆
- 关于碰到优盘插入电脑检测到病毒并且优盘里文件只显示System Volume Information文件夹的问题解决。
- 在java中 以下关于集合框架_在Java中LinkedList类和ArrayList类同属于集合框架类,下列...
- 帆软FineReport8.0使用技巧总结及常见问题解决
- MySQL 日期字符串转换
- warning: LF will be replaced by CRLF in bispython/venv/Lib/site-packages/dja
- 伪类选择器和伪元素选择器