关于控件的Invoke(...)方法和BeginInvoke(...)方法的区别
这两个方法最主要的区别就是一个是同步,一个是异步,即会阻塞线程,那么阻塞哪个线程呢?我们用代码来分析(工具是VS2010)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading; namespace Invoke和BeginInvoke
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
} private void button1_Click(object sender, EventArgs e)
{
// HH 是24小时制,hh是12小时制
MessageBox.Show(Thread.CurrentThread.GetHashCode()+" AAA "+DateTime.Now.ToString(" HH.mm.ss.fffff"));
Thread thd = new Thread(ThreadMethod);
thd.IsBackground = true; // 设置为后台线程,该线程即使没有执行完也会随着主线程退出而退出。
thd.Start();
Thread.Sleep();
MessageBox.Show(Thread.CurrentThread.GetHashCode() + " EEE " + DateTime.Now.ToString(" HH.mm.ss.fffff "));
} private void ThreadMethod()
{
MessageBox.Show(Thread.CurrentThread.GetHashCode() + " BBB " + DateTime.Now.ToString("HH.mm.ss.fffff"));
// Invoke会阻塞 ThreadMethod() 所在的线程(子线程)
label1.Invoke(new Action(InvokeMethod)); // Flag
MessageBox.Show(Thread.CurrentThread.GetHashCode() + " DDD " + DateTime.Now.ToString("HH.mm.ss.fffff"));
} private void InvokeMethod()
{
MessageBox.Show(Thread.CurrentThread.GetHashCode() + " CCC " + DateTime.Now.ToString("HH.mm.ss.fffff"));
}
}
}
将上面代码运行后(我这个是个窗体,有个label1和button1,且button1有Click事件),首先是MessageBox.Show(...)会阻塞主线程,如果不按掉AAA的那个显示框不会继续执行代码。
按掉AAA后立刻出现BBB,然后有两种情况,很重要:
①等待3000毫秒的样子出现EEE框,这时候再按掉BBB,这时候会执行InvokeMethod(),该函数是由创建label1的线程来执行。这时候弹出CCC,因为Invoke(...)本身会阻塞子线程ThreadMethod,故没有点掉CCC是不会出现DDD的
②点掉AAA后立刻点掉BBB,此时执行ThreadMethod中的label1.Invoke(...),这句代码拥有“两种阻塞”,第一种Invoke本身就是同步函数,故它会阻塞线程ThreadMethod,使得label1.Invoke(...)执行完之前(而它是否执行完又取决于线程InvokeMethod)不会弹出DDD来(即没有按掉CCC前不会弹出DDD)。第二种阻塞就是label1.Invoke是一个很特别的函数,他会使得系统让主线程(因为是主线程创建的label1)来执行label1.Invoke(...)中的方法,即InvokeMethod,而此时主线程正在Sleep(3000),故这段时间内将不会弹出CCC的提示框,等主线程Sleep(3000)完毕后首先弹出的是CCC而不是EEE(即label1.Invoke(...)会将InvokeMethod()放在其所在线程优先执行),
且情况②如果不点掉CCC不会出现DDD和EEE(这里要注意,尽管不点掉CCC会同时阻塞主线程和子线程,但是阻塞子线程是因为label1.Invoke(...)是同步的,没有执行玩InvokeMethod() Invoke()也不会结束;而阻塞主线程的不是
Invoke(),而是因为InvokeMethod()是在主线程中执行的,MessageBox.Show(...."CCC"...)阻塞了主线程,与label1.Invoke(...)无关),点掉CCC后,立刻“同时”执行DDD和EEE。
将Invoke换成BeginInvoke(...)后,同样②情况,上面的阻塞情况不会发生,即 即使CCC没有点掉也会接着执行DDD(因为label1.BeginInvoke(...)不会阻塞ThreadMethod(),但是注意!!!EEE在CCC没有点掉之前是不会执行的(且仍要等主线程Sleep(3000)后才会弹出CCC提示框),因为阻塞EEE的是InvokeMethod()中的MessageBox.Show(.CCC..)。
关于控件的Invoke(...)方法和BeginInvoke(...)方法的区别的更多相关文章
- M方法和D方法的区别
M方法和D方法的区别 ThinkPHP 中M方法和D方法都用于实例化一个模型类,M方法 用于高效实例化一个基础模型类,而 D方法 用于实例化一个用户定义模型类. 使用M方法 如果是如下情况,请考虑使用 ...
- JAVA反射中的getFields()方法和getDeclaredFields ()方法的区别
JAVA反射中的getFields()方法和getDeclaredFields ()方法的区别 关于获取类的字段有两种方式:getFields()和getDeclaredFields().我们先来 ...
- ThinkPHP的D方法和M方法的区别
M方法和D方法的区别 ThinkPHP 中M方法和D方法都用于实例化一个模型类,M方法 用于高效实例化一个基础模型类,而 D方法 用于实例化一个用户定义模型类. 使用M方法 如果是如下情况,请考虑使用 ...
- Exception 的 toString() 方法和 getMessage() 方法的区别
Exception 的 toString() 方法和 getMessage() 方法的区别: 在开发的过程中打印错误日志时尽量使用e.toString() 方法, 因为当错误为空指针时 e.getMe ...
- ExtJS中listener方法和handler方法的区别
listener方法和handler方法的区别在文档中的说明的太玄乎了,看不懂 listeners监听能够对一个click Event事件添加任意多个的事件响应处理函数 而handler处理只能够通过 ...
- MongoDB save()方法和insert()方法的区别
MongoDB save()方法和insert()方法的区别 首先看官方文档怎么说的 Updates an existing document or inserts a new document, d ...
- 问题:ExecuteNonQuery 与 ExecuteScalar 结果: ExecuteNonQuery方法和ExecuteScalar方法的区别
ExecuteNonQuery方法和ExecuteScalar方法的区别 ----ExecuteNonQuery():执行命令对象的SQL语句,返回一个int类型变量,如果SQL语句是对数据库的记录进 ...
- 2016/05/23 thinkphp M方法和D方法的区别
M方法和D方法的区别 ThinkPHP 中M方法和D方法都用于实例化一个模型类,M方法 用于高效实例化一个基础模型类,而 D方法 用于实例化一个用户定义模型类. 使用M方法 如果是如下情况,请考虑使用 ...
- GET方法和POST方法的区别,Get方法到底可传递的字符串的最大长度是多少?
GET方法和POST方法的区别,Get方法到底可传递的字符串的最大长度是多少?曾经人介绍,如果使用GET方式传输参数,URL的最大长度是256个字节,对此深信不疑. 但是最近看到一些超长的url,能够 ...
随机推荐
- 个人理解c#对称加密 非对称加密 散列算法的应用场景
c#类库默认实现了一系列加密算法在System.Security.Cryptography; 命名空间下 对称加密 通过同一密匙进行加密和解密.往往应用在内部数据传输情况下.比如公司a程序 和B程序 ...
- Sublime Text编辑器的12个技巧和诀窍
本文为您提供Sublime Text编辑器的12个技巧和诀窍,深入挖掘这个看似简洁的代码编辑器,背后所隐藏的实现各种高级功能的无限可能. 1) 选择 以下是一些Sublime Text选择文本的快捷键 ...
- JS控制,返回上一页之后强行刷新一次
网站建设过程中,提交页面后我们经常要用到window.history.go(-1)返回上一页,因为页面的缓存功能,我们只能返回上次操作的页面,但在删除等操作中,我们希望实时看到删除项目后的页面,这就要 ...
- css3 背景渐变
本来想先瞎扯些什么,然后又不知道讲什么的好,那就直接进入正题吧. 参考资料: Using CSS gradients (以及该页面内的大部分链接页面的资料) 首先区分下,平常给的纯色backgrou ...
- PHP判断SESSION过期的方法
在公共函数function.php中添加如下方法,即可控制用户登录的SESSION有效期 //封装SESSION过期判断方法function start_session($expire = 0){ $ ...
- .NET FRAMEWORK版本:4.0.30319; ASP.NET版本:4.6.118.0
https://gqqnbig.me/2015/11/23/net-framework%e7%89%88%e6%9c%ac4-0-30319-asp-net%e7%89%88%e6%9c%ac4-6- ...
- logstash-5.0同步mysql
环境 Windows10企业版X64 安装logstash-input-jdbc插件 进入logstash/bin/目录,命令: logstash-plugin install logstash-in ...
- EmployeeTest
package fourthf; public class EmployeeTest { public static void main(String[] args) { // TODO Auto-g ...
- zen Code 支持的代码样式
这里是一个支持的属性和操作符的列表: E 元素名称(div, p); E#id 使用id的元素(div#content, p#intro, span#error); E.class 使用类的元素(di ...
- 又一枚精彩的弹幕效果jQuery实现
精彩的弹幕效果分享给大家,具有一定的参考价值,感兴趣的朋友可以尝试制作弹幕,具体内容如下 简易弹幕效果:将发布的内容随机显示在弹幕右侧,逐渐左移最后消失. 涉及知识点:val().random ...