这两个方法最主要的区别就是一个是同步,一个是异步,即会阻塞线程,那么阻塞哪个线程呢?我们用代码来分析(工具是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(...)方法的区别的更多相关文章

  1. M方法和D方法的区别

    M方法和D方法的区别 ThinkPHP 中M方法和D方法都用于实例化一个模型类,M方法 用于高效实例化一个基础模型类,而 D方法 用于实例化一个用户定义模型类. 使用M方法 如果是如下情况,请考虑使用 ...

  2. JAVA反射中的getFields()方法和getDeclaredFields ()方法的区别

    JAVA反射中的getFields()方法和getDeclaredFields ()方法的区别   关于获取类的字段有两种方式:getFields()和getDeclaredFields().我们先来 ...

  3. ThinkPHP的D方法和M方法的区别

    M方法和D方法的区别 ThinkPHP 中M方法和D方法都用于实例化一个模型类,M方法 用于高效实例化一个基础模型类,而 D方法 用于实例化一个用户定义模型类. 使用M方法 如果是如下情况,请考虑使用 ...

  4. Exception 的 toString() 方法和 getMessage() 方法的区别

    Exception 的 toString() 方法和 getMessage() 方法的区别: 在开发的过程中打印错误日志时尽量使用e.toString() 方法, 因为当错误为空指针时 e.getMe ...

  5. ExtJS中listener方法和handler方法的区别

    listener方法和handler方法的区别在文档中的说明的太玄乎了,看不懂 listeners监听能够对一个click Event事件添加任意多个的事件响应处理函数 而handler处理只能够通过 ...

  6. MongoDB save()方法和insert()方法的区别

    MongoDB save()方法和insert()方法的区别 首先看官方文档怎么说的 Updates an existing document or inserts a new document, d ...

  7. 问题:ExecuteNonQuery 与 ExecuteScalar 结果: ExecuteNonQuery方法和ExecuteScalar方法的区别

    ExecuteNonQuery方法和ExecuteScalar方法的区别 ----ExecuteNonQuery():执行命令对象的SQL语句,返回一个int类型变量,如果SQL语句是对数据库的记录进 ...

  8. 2016/05/23 thinkphp M方法和D方法的区别

    M方法和D方法的区别 ThinkPHP 中M方法和D方法都用于实例化一个模型类,M方法 用于高效实例化一个基础模型类,而 D方法 用于实例化一个用户定义模型类. 使用M方法 如果是如下情况,请考虑使用 ...

  9. GET方法和POST方法的区别,Get方法到底可传递的字符串的最大长度是多少?

    GET方法和POST方法的区别,Get方法到底可传递的字符串的最大长度是多少?曾经人介绍,如果使用GET方式传输参数,URL的最大长度是256个字节,对此深信不疑. 但是最近看到一些超长的url,能够 ...

随机推荐

  1. 个人理解c#对称加密 非对称加密 散列算法的应用场景

    c#类库默认实现了一系列加密算法在System.Security.Cryptography; 命名空间下 对称加密 通过同一密匙进行加密和解密.往往应用在内部数据传输情况下.比如公司a程序 和B程序 ...

  2. 【转载】STL之priority_queue

    参考资料:传送门先回顾队列的定义:队列(queue)维护了一组对象,进入队列的对象被放置在尾部,下一个被取出的元素则取自队列的首部.priority_queue特别之处在于,允许用户为队列中存储的元素 ...

  3. HTML5学习总结-番外04 Cordova/PhoneGap

    一 PhoneGap 1 PhoneGap简绍 http://www.cnblogs.com/JustRun1983/p/3819433.html 2 环境安装 http://cordova.apac ...

  4. Delphi 获取时间的年月日

    procedure TFrmLltj.FormActivate(Sender: TObject); var   Present: TDateTime;   Year, Month, Day, Hour ...

  5. 使用GRUB 添加新的启动项 (menu entry)

    GRUB版本: Grub2 基础知识: 相关的文件和目录结构: A./etc/grub.d/ 上图中有一个40_custom的脚本: 可以通过修改40_custom脚本来加入自定义的启动项. B./e ...

  6. centos7安装svn1.8.16

    svn下载地址:http://subversion.apache.org/download/ svn要依赖一些包,可以提前装好 yum -y install apr-util apr-util-dev ...

  7. Yii2 基于RESTful架构的 advanced版API接口开发 配置、实现、测试 (转)

    环境配置: 开启服务器伪静态 本处以apache为例,查看apache的conf目录下httpd.conf,找到下面的代码 LoadModule rewrite_module modules/mod_ ...

  8. 第一章 --- 关于Javascript 设计模式 之 单例模式

    首先我们对单例模式先进行理论上的讲解,接下来,我们再通过具体的代码示例,来讲解,这个单例模式的使用场景和这种模式的优缺点 (这个系列的所有关于设计模式的都是面向Javascript) 一.理论定义: ...

  9. Notepad++源码编译及其分析

    Notepad++是一个小巧精悍的编辑器,其使用方法我就不多说了,由于notepad++是使用c++封装的windows句柄以及api来实现的,因此对于其源码的研究有助于学习如何封装自己简单的库(当然 ...

  10. 通过openswan基于Azure平台搭建VPN server

    用过Azure的读者都知道,Vnet一直是Azure比较自豪的地方,尤其是VPN,Azure提供了两种VPN以及专线来保证客户数据的安全性,S2S vpn(站点到站点的,基于IPsec的),P2S v ...