我们先看个简单的例子:

        private void Window_Loaded(object sender, RoutedEventArgs e)
{
Console.WriteLine("BeforeInvoke1");
Dispatcher.Invoke((Action)(() => {
Thread.Sleep(1000);
Console.WriteLine("Invoke1");
}));
Console.WriteLine("EndInvoke1"); Console.WriteLine("BeforeInvoke2");
Dispatcher.BeginInvoke((Action)(() => {
Thread.Sleep(1000);
Console.WriteLine("BeginInvoke2");
}));
Console.WriteLine("EndInvoke2");
}  

执行的结果为:

以上结果说明,Invoke为同步,必须等待其中的委托完成后才能向后执行

         BeginInvoke为异步,不必等待它所委托的方法完成后再执行(比较类似的有其他Begin方法)

首先说下,invoke和begininvoke的使用有两种情况:

1. control中的invoke、begininvoke。

2. delegrate中的invoke、begininvoke。

这两种情况是不同的,我们这里要讲的是第1种。下面我们在来说下.NET中对invoke和begininvoke的官方定义。

control.invoke(参数delegate)方法:在拥有此控件的基础窗口句柄的线程上执行指定的委托。

control.begininvoke(参数delegate)方法:在创建控件的基础句柄所在线程上异步执行指定委托。

根据这两个概念我们大致理解invoke表是同步、begininvoke表示异步。但是如何来进行同步和异步呢?我们来做一个测试。

invoke 例子:

 private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"AAA");
invokeThread = new Thread(new ThreadStart(StartMethod)); invokeThread.Start();
string a = string.Empty;
for (int i = ; i < ; i++) //调整循环次数,看的会更清楚
{
Thread.Sleep(); a = a + "B";
}
MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+a);
} private void StartMethod()
{
MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"CCC"); button1.Invoke(new invokeDelegate(invokeMethod)); MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"DDD");
} private void invokeMethod()
{ //Thread.Sleep(3000);
MessageBox.Show (Thread.CurrentThread.GetHashCode().ToString()+ "EEE");
} 结论:我们运行后,看下程序的运行顺序,1AAA->3CCC和1BBB->1EEE ->3DDD 。

结论:我们运行后,看下程序的运行顺序,1AAA->3CCC和1BBB->1EEE ->3DDD 。

解释:主线程运行1AAA,然后1BBB和子线程3CCC同时执行,然后通过invoke来将invokemethod方法提交给主线程,然后子线程等待主线程执行,直到主线程将invokemethod方法执行完成(期间必须等待主线程的任务执行完成,才会去执行invoke提交的任务),最后执行子线程3DDD。

begininvoke 例子:

private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"AAA");
invokeThread = new Thread(new ThreadStart(StartMethod)); invokeThread.Start();
string a = string.Empty;
for (int i = ; i < ; i++) //调整循环次数,看的会更清楚
{
Thread.Sleep(); a = a + "B";
}
MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+a);
} private void StartMethod()
{
MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"CCC");
button1.BeginInvoke(new invokeDelegate(invokeMethod)); MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString()+"DDD");
} private void beginInvokeMethod()
{
//Thread.Sleep(3000);
MessageBox.Show(Thread.CurrentThread.GetHashCode().ToString() + "EEEEEEEEEEEE");
}

结论: 我们运行后看看执行的结果:1AAA->1BBB和3CCC->1EEE和3DDD。

解释: 主线程运行1AAA,然后1BBB和子线程3CCC同时执行,然后通过begininvoke来将invokemethod方法提交给主线程,然后主线程执行1EEE(主线程自己的任务执行完成), 同时子线程继续执行3DDD。

通过这个两段代码的测试比较,我们会发现其实invoke和begininvoke所提交的委托方法都是在主线程中执行的,其实根据我invoke和begininvoke的定义我们要在子线程中来看这个问题,在invoke例子中我们会发现invoke所提交的委托方法执行完成后,才能继续执行DDD;在begininvoke例子中我们会发现begininvoke所提交的委托方法后,子线程讲继续执行DDD,不需要等待委托方法的完成。 那么现在我们在回想下invoke(同步)和begininvoke(异步)的概念,其实它们所说的意思是相对于子线程而言的,其实对于控件的调用总是由主线程来执行的。我们很多人搞不清这个同步和异步,主要还是因为我们把参照物选错了。其实有时候光看概念是很容易理解错误的。

invoke和beginInvoke的更多相关文章

  1. C# Invoke或者BeginInvoke的使用

    在Invoke或者BeginInvoke的使用中无一例外地使用了委托Delegate. 一.为什么Control类提供了Invoke和BeginInvoke机制? 关于这个问题的最主要的原因已经是do ...

  2. C#中Invoke 和 BeginInvoke 的区别

    Control.Invoke 方法 (Delegate) :在拥有此控件的基础窗口句柄的线程上执行指定的委托. Control.BeginInvoke 方法 (Delegate) :在创建控件的基础句 ...

  3. 控件的invoke和beginInvoke方法

    System.Windows.Forms.Timer 的timer是在主线程上执行的,因此在timer的tick事件中操作界面上的控件不会发生线程的安全性检测. Control的invoke和begi ...

  4. C#的Invoke和BeginInvoke

    在Invoke或者BeginInvoke的使用中无一例外地使用了委托Delegate,至于委托的本质请参考我的另一随笔:对.net事件的看法. 一.为什么Control类提供了Invoke和Begin ...

  5. 在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke

    今天关闭一个窗体,报出这样的一个错误"在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke.",这个不用多想,肯定是那个地方没有释放掉.既然碰到这个问题, ...

  6. 安装SQL Server出现在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke的错误解决办法

    以下是错误报告:   标题: SQL Server 安装程序失败. ------------------------------   SQL Server 安装程序遇到以下错误:   在创建窗口句柄之 ...

  7. [整][转]Invoke和BeginInvoke的使用

    在Invoke或者BeginInvoke的使用中无一例外地使用了委托Delegate. 一.为什么Control类提供了Invoke和BeginInvoke机制? 关于这个问题的最主要的原因已经是do ...

  8. c#多线程(UI线程,控件显示更新) Invoke和BeginInvoke 区别

    如果只是直接使用子线程访问UI控件,直接看内容三,如果想深入了解从内容一看起. 一.Control.Invoke和BeginInvoke方法的区别 先上总结: Control.Invoke 方法 (D ...

  9. Dispatcher中Invoke与BeginInvoke

    [同步]Invoke Application.Current.Dispatcher.Invoke(AutoIncreaseNumber); [异步]BeginInvoke Application.Cu ...

随机推荐

  1. java 8种基本数据类型

    数值型--> 整  型:int,short,long,byte 浮点型:double,float 字符型-->char 布尔型-->boolean

  2. 数据库中is null(is not null)与=null(!=null)的区别

    在标准SQL语言(ANIS SQL)SQL-92规定的Null值的比较取值结果都为False,既Null=Null取值也是False.NULL在这里是一种未知值,千变万化的变量,不是“空”这一个定值! ...

  3. ls -l 列表信息详解

    我们平时用ls -l 命令查看一个目录下的文件和子目录的详悉信息时,会得到一个详细的文件和目录名列表.这个列表包含了文件的属性,所属用户,所属组,创建时间,文件大小等等信息.这些信息到底是什么意思呢? ...

  4. 夺命雷公狗---微信开发62----所以memcache对access_token进行全局缓存优化

    公众号调用接口并不是无限制的,为了防止公众号的程序错误而引发微信服务器负载异常,默认情况下, 每个公众号调用接口都不能超过一定限制,当超过一定限制时,调用对应接口会收到错误信息,造成调用失败. 我们也 ...

  5. zw版【转发·台湾nvp系列Delphi例程】HALCON AffineTransRegion

    zw版[转发·台湾nvp系列Delphi例程]HALCON AffineTransRegion unit Unit1;interfaceuses Windows, Messages, SysUtils ...

  6. Debian类系统必做——将【你的用户】加入sudoers用户组

    切换到root:su root   修改sudoers nano /etc/sudoers 在root    ALL=(ALL:ALL) ALL下,加入:liz        ALL=(ALL:ALL ...

  7. iBatis面试题

    1) Ibatis中使用like ‘%#filedName#%’ 时,有什么问题? 在xml映射文件中,如果直接按如上写法,会报异常:java.sql.SQLException: Invalid ar ...

  8. 鸟哥的Linux私房菜之学习shell script

    运行程序的时候一般都是创建一个子程序来执行,所以子程序中的变量什么的在当前的shell下没法使用,但是如果使用source来执行就可以在当前shell下执行程序 shift 1 去掉第一个参数,后面接 ...

  9. Delphi 调用 Rest 服务的一些

    1.关于数据接收的格式 测试发现获取的json源数据中间汉字的地方是乱码,导致引号不配对,引发内存错误. TIdHttp在获取数据之前,要将定义的TStringStream的Encoding设置为UT ...

  10. ServiceStack.Redis 使用教程

    http://www.cnblogs.com/shanyou/archive/2011/11/10/2245082.html https://github.com/ServiceStack/Servi ...