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

    来源:蝴蝶之梦天使 链接:http://www.jianshu.com/p/d333cf6ae4b0 四十.AFNetworking 传送 form-data 将JSON的数据,转化为NSData, ...

  2. 面向对象继承 (for in 原型链查找属性)

    window.onload=function(){ new Preson('liujian','男').show(); new Work('liujian','男','工人').show(); new ...

  3. 网站引入了css样式文件能访问,就是没有效果

    今天后端的同事遇到这么个问题,引入了外部css文件也能访问,就是页面上没有效果. 大概是下面这个样子: css引入如下: 我非常的纳闷,说真的我还没遇到过这种情况,UI是可以运行的,一点事都没有... ...

  4. DataTable DataRow DataColumn DataSet

    1.DataTable 数据表(内存) 2.DataRow DataTable 的行 3.DataColumn DataTable 的列 4.DataSet 内存中的缓存

  5. CentOS 7.1编译安装PHP7

    原文: https://typecodes.com/web/centos7compilephp7.html?utm_source=tuicool&utm_medium=referral 1 创 ...

  6. unsilder中的jq深入学习

    //trigger $('#foo').on('click', function() { alert($(this).text()); }); $('#foo').trigger('click'); ...

  7. 如何使用git命令添加文件和提交文件

    1.进入指定文件夹内,启动 git bash here 2. 初始化文件夹 git init 3.开始添加文件 所有文件添加方法 git add . 单个文件添加方法 git add *.* 例如我的 ...

  8. [译]初识.NET Core & ASP.NET Core

    原文:点这 本文的源代码在此: ASP.NET From Scratch Sample on GitHub 你过你是.NET Core的入门者,你可以先看看下面这篇文章: ASP.NET and .N ...

  9. R自动数据收集第一章概述——《List of World Heritage in Danger》

      导包     library(stringr) library(XML) library(maps) heritage_parsed <- htmlParse("http://en ...

  10. Linux2.6.11版本:classic RCU的实现

    转载自:http://www.wowotech.net/kernel_synchronization/linux2-6-11-RCU.html 一.前言 无论你愿意或者不愿意,linux kernel ...