我们先看个简单的例子:

        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. Python学习总结2:raw_input() 与 input()

    参考http://www.cnblogs.com/way_testlife/archive/2011/03/29/1999283.html 1. 输入数据要求 raw_input() 直接读取控制台的 ...

  2. Android 5.0新特性了解(一)----TabLayout

    1.在2015年的google大会上,google发布了新的Android Support Material Design库,里面包含了几个新的控件,其中就有一个TabLayout,它就可以完成Tab ...

  3. cometd使用-bayeux协议(读法:贝叶)

    bayeux.createChannelIfAbsent("/**", new ServerChannel.Initializer() { @Override public voi ...

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

    zw版[转发·台湾nvp系列Delphi例程]HALCON FillUpShape2 procedure TForm1.Button1Click(Sender: TObject);var op : H ...

  5. 给Debian安装Xfce桌面

    1.sudo apt-get install xorg xdm xfce4   2.vi ~/.xinitrc,然后输入:exec xfce4,在终端输入startx命令后就能进入xfce4,或直接在 ...

  6. 二招解决php乱码问题

    PHP的乱码问题已经说了N+1遍了,但还是经常看到新手不知道该如何解决php乱码问题,在此本人再重新给总结一下,希望对新手有点帮助 php网页出现乱码一般是在建立数据库时用的编码和php网页的编码不同 ...

  7. 解析php mysql 事务处理回滚操作

    论坛扣币项目中,用户支付论坛币的时候如果突然断网.电脑死机.停电.等其它自然灾害时,导致本次交易没有成功(即用户的币已经扣掉了,但是服务器数据库中没有消费记录等其它情况),这种情况应该怎么样进行处理呢 ...

  8. SQL分组取每组前一(或几)条记录(排名)

    mysql分组取每组前几条记录(排名) 附group by与order by的研究 http://www.jb51.net/article/31590.htm --按某一字段分组取最大(小)值所在行的 ...

  9. 向已写好的多行插入sql语句中添加字段和值

    #region 添加支款方式--向已写好的多行插入sql语句中添加字段和值 public int A_ZhifuFS(int diqu) { ; string strData = @"SEL ...

  10. 【海岛帝国系列赛】No.5 海岛帝国:独立之战

    50229234海岛帝国:独立之战 [试题描述] 恐怖分子多年来一直如饥似渴地渴求“药师傅”帝国,但是,“里脊肉”BANNIE时刻在守护着这一方水土.从而使帝国日益强大.如今,BANNIE由于在 “牡 ...