作者:EasonLeung

一、Delegate的Invoke、BeginInvoke

1、Delegate.Invoke (委托同步调用)

  a、委托的Invoke方法,在当前线程中执行委托。

  b、委托执行时阻塞当前线程,知道委托执行完毕,当前线程才继续向下执行。

  c、委托的Invoke方法,类似方法的常规调用。

2、Delegate.BeginInvoke (委托异步调用)

  a、委托的BeginInvoke方法,在线程池分配的子线程中执行委托

  b、委托执行时不会阻塞主线程(调用委托的BeginInvoke线程),主线程继续向下执行。

  c、委托执行时会阻塞子线程。

  d、委托结束时,如果有返回值,子线程讲返回值传递给主线程;如果有回调函数,子线程将继续执行回调函数。

3、Demo

  a、Delegate

         private void btn_General_Click(object sender, EventArgs e)
{
txt_Message.Text = "";
txt_Message.Text += "主线程:"+ Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n";
//委托方法,在调用委托的线程中执行,本例中就是主线程(UI线程)。
//执行一些耗时的操作,就会阻塞主线程(UI线程)
//委托的普通调用就等于方法的直接调用,del();等价于SomeWork();
del();
//SomeWork();
txt_Message.Text += "\r\n主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n";
}

   b、Delegate.Invoke

         private void btn_Main_Invoke_Click(object sender, EventArgs e)
{
txt_Message.Text = "";
txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n";
//委托的同步调用,其实就是等价于委托的普通调用。
del.Invoke();
txt_Message.Text += "\r\n主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n";
}
         private void btn_Sub_Invoke_Click(object sender, EventArgs e)
{
txt_Message.Text = "";
txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n"; //开启新的线程执行委托,主线程(UI线程)继续向下执行
new Thread(() => {
txt_Message.Text += "\r\n----子线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n";
//委托在调用线程中执行,并阻塞调用线程,知道委托方法执行结束。
del.Invoke();
txt_Message.Text += "\r\n----子线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n";
}).Start(); txt_Message.Text += "\r\n主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n";
}

  c、Delegate.BeginInvoke

         private void btn_Main_BeginInvoke_Click(object sender, EventArgs e)
{
txt_Message.Text = "";
txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n";
//委托异步调用
//1、委托方法,在线程池中分配的子线程中执行。
//2、主线程和子线程同时执行。
//3、子线程结束之后,如果有返回值得话,将返回值传递给主线程。如果有回调函数的话,继续在子线程中执行回调函数。 //有异常,控件不能在子线程中访问修改。
//避免这类异常有两种方法
//1、手动关闭控件的跨线程安全检查Control.CheckForIllegalCrossThreadCalls = false;(不建议使用)
//2、使用控件的Invoke方法。(推荐使用)
del.BeginInvoke(null,null);
txt_Message.Text += "\r\n主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n";
}
         private void btn_Sub_BeginInvoke_Click(object sender, EventArgs e)
{
txt_Message.Text = "";
txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n"; //开启新的线程执行委托,主线程(UI线程)继续向下执行
new Thread(() =>
{
txt_Message.Text += "\r\n----子线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n";
//在线程池中分配的子线程中执行委托方法,调用委托的线程继续向下执行。
del.BeginInvoke(null, null);
txt_Message.Text += "\r\n----子线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n";
}).Start(); txt_Message.Text += "\r\n主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n";
}



作者:EasonLeung

二、Control的Invoke、BeginInvoke

1、Control.Invoke (同步调用)  

  (1)在主线程(UI线程)中调用Control.Invoke

    a、在主线程(UI线程)中调用Control.Invoke,先执行Invoke的方法,再执行Invoke后面的代码。

  (2)在子线程中调用Control.Invoke

    a、子线程中调用Control.Invoke,子线程将调用的方法封装成消息,调用API的RegisterWindowMessage()向UI窗口发送消息。 主线程继续向下执行,子线程处于阻塞状态。

    b、当该消息被主线程执行完成后,子线程才能继续往下执行。

2、Delegate.BeginInvoke (异步调用)

  (1)在主线程(UI线程)中调用Control.BeginInvoke

    a、在主线程(UI线程)中调用Control.BeginInvoke,将调用的方法封装成消息,调用API的RegisterWindowMessage()向UI窗口发送消息。先执行Invoke后面的代码,再执行Invoke的方法。

  (2)在子线程中调用Control.BeginInvoke

    a、子线程中调用Control.BeginInvoke,子线程将调用的方法封装成消息,调用API的RegisterWindowMessage()向UI窗口发送消息。主线程继续向下执行,子线程也继续向下执行。

    b、最后由主线程执行Invoke的方法。

3、Demo

  a、在主线程(UI线程)中调用Control.Invoke

         private void btn_Main_Invoke_Click(object sender, EventArgs e)
{
//执行顺序:代码A -> 代码Invoke -> 代码B
//都是在主线程中执行 txt_Message.Text = "";
txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n";
//代码A
this.txt_Message.Invoke(del);
//代码B
txt_Message.Text += "\r\n主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n";
}

  b、在子线程中调用Control.Invoke

         private void btn_Sub_Invoke_Click(object sender, EventArgs e)
{
//执行顺序:
//1、代码A(主线程执行)
//2、代码D(主线程执行) 和 代码B(子线程执行) 并发执行
//3、封装消息,并在UI线程中注册消息(子线程执行)
//4、代码Invoke(主线程执行)
//5、代码C(子线程执行) txt_Message.Text = "";
txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n";
//代码A
new Thread(() =>
{
//代码B
int temp = ;
this.txt_Message.Invoke(del);
//代码C
temp = ;
}).Start();
//代码D
txt_Message.Text += "\r\n主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n";
}

  c、在主线程(UI线程)中调用Control.BeginInvoke

         private void btn_Main_BeginInvoke_Click(object sender, EventArgs e)
{
//执行顺序:代码A -> 封装消息,并在UI线程中注册消息 -> 代码B -> 代码Invoke
//都是在主线程中执行 txt_Message.Text = "";
txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n";
//代码A
this.txt_Message.BeginInvoke(del);
//代码B
txt_Message.Text += "\r\n主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n";
}

  c、在子线程中调用Control.BeginInvoke

         private void btn_Sub_BeginInvoke_Click(object sender, EventArgs e)
{
//执行顺序:
//1、代码A(主线程执行)
//2、代码D(主线程执行) 和 代码B(子线程执行) 并发执行
//3、封装消息,并在UI线程中注册消息(子线程执行)
//4、代码C(子线程执行)
//5、代码Invoke(主线程执行) txt_Message.Text = "";
txt_Message.Text += "主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始工作\r\n";
//代码A
new Thread(() =>
{
//代码B
int temp = ;
this.txt_Message.BeginInvoke(del);
//代码C
temp = ;
}).Start();
//代码D
txt_Message.Text += "\r\n主线程:" + Thread.CurrentThread.ManagedThreadId + "---开始结束\r\n";
}

代码下载

C#Delegate.Invoke、Delegate.BeginInvoke And Control.Invoke、Control.BeginInvoke的更多相关文章

  1. (转)C# Delegate.Invoke、Delegate.BeginInvoke

    Delegate的Invoke.BeginInvoke 1.Delegate.Invoke (委托同步调用) a.委托的Invoke方法,在当前线程中执行委托. b.委托执行时阻塞当前线程,知道委托执 ...

  2. C# Control.BeginInvoke、synchronizationcontext.post、delegate.BeginInvoke的运行原理

    背景 用到的知识点 1.windows消息机制 备注:鼠标点击.键盘等事件产生的消息要放入系统消息队列,然后再分配到应用程序线程消息队列.软件PostMessage的消息直接进入应用程序线程消息队列, ...

  3. (转)c# control.Invoke control.BeginInvoke

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

  4. WinForm二三事(三)Control.Invoke&Control.BeginInvoke

    http://www.cnblogs.com/yuyijq/archive/2010/01/11/1643802.html 这个系列从2009年写到2010年,差点又成太监文.随着WPF/Silver ...

  5. C#中的线程二(Cotrol.BeginInvoke和Control.Invoke)

    C#中的线程二(Cotrol.BeginInvoke和Control.Invoke) 原文地址:http://www.cnblogs.com/whssunboy/archive/2007/06/07/ ...

  6. 关于Action<T> 、Func<T>、EventHandler<T>、event、delegate

    c# 最初的时候 只有 delegate,之后的版本封装了Action<T> .Func<T>.EventHandler<T> 关于Action<T>  ...

  7. Control.Invoke和Control.BeginInvoke

    问题的引入 下面有个简单的demo,大家一看代码就知道效果如何示例.我新建一个winform的程序,然后写入了如下代码: using System; using System.Windows.Form ...

  8. 千万别在UI线程上调用Control.Invoke和Control.BeginInvoke,因为这些是依然阻塞UI线程的,造成界面的假死

    原文地址:https://www.cnblogs.com/wangchuang/archive/2013/02/20/2918858.html .c# Invoke和BeginInvoke 区别 Co ...

  9. 并发编程概述 委托(delegate) 事件(event) .net core 2.0 event bus 一个简单的基于内存事件总线实现 .net core 基于NPOI 的excel导出类,支持自定义导出哪些字段 基于Ace Admin 的菜单栏实现 第五节:SignalR大杂烩(与MVC融合、全局的几个配置、跨域的应用、C/S程序充当Client和Server)

    并发编程概述   前言 说实话,在我软件开发的头两年几乎不考虑并发编程,请求与响应把业务逻辑尽快完成一个星期的任务能两天完成绝不拖三天(剩下时间各种浪),根本不会考虑性能问题(能接受范围内).但随着工 ...

随机推荐

  1. OpenGL遮挡查询

    转自:http://www.cnblogs.com/mazhenyu/p/5083026.html 在一个场景中,如果有有些物体被其他物体遮住了不可见.那么我们就不需要绘制它.在复杂的场景中,这可以减 ...

  2. Python requests介绍之接口介绍

    Python requests介绍 引用官网介绍 Requests 唯一的一个非转基因的 Python HTTP 库,人类可以安全享用. Requests 允许你发送纯天然,植物饲养的 HTTP/1. ...

  3. 修改unity变量名但不丢失序列化值

    using UnityEngine; using UnityEngine.Serialization; public class LgsTest : MonoBehaviour { [Formerly ...

  4. JS循环汇总

    JS循环汇总 一.总结 一句话总结:js中的循环主要有while.for.for...in.for...of,循环是,要区别不同的循环对象,比如对象,数组,集合等 while for for...in ...

  5. ArcGis For Silverlight API,地图显示Gis,绘制点,线,绘制图等--绘制点、线、圆,显示提示信息

    ArcGis For Silverlight API,地图显示Gis,绘制点,线,绘制图等--绘制点.线.圆,显示提示信息 /// <summary> /// 绘制界面上的点和线 ///  ...

  6. Rspec: everyday-rspec实操: 第8章DRY. (6个方法,其中3个方法好上手)

    Don't Repeat Yourself. • 把操作步骤提取到辅助模块中;✅ • 通过let复用测试中的实例变量;✅ • 把通用的设置移到共享的情景中;⚠️(不喜欢) • 在RSpec和rspec ...

  7. 微信小程序------MD5加密(支持中文和不支持中文)和网络请求(get和post)

    开发中常常遇到MD5加密,最近做小程序也用到了,简单总结了一下: 这要有两个加密文件,一个不支持中文,一个支持,所以你选择支持的来用就行了: 也随便说说小程序的get和post网络请求. 来看看效果图 ...

  8. Confluence 6 导入 Active Directory 服务器证书 - Windows

    为了让你的应用服务器能够信任你的目录服务器.你目录服务器上导出的证书需要导入到你应用服务器的 Java 运行环境中.JDK 存储了信任的证书,这个存储信任证书的文件称为一个 keystore.默认的 ...

  9. Elections CodeForces - 1020C (贪心)

    大意: 有n个选民, m个党派, 第i个选民初始投$p_i$一票, 可以花费$c_i$改变投票, 求最少花费使得第一个党派的票数严格最大 假设最终第一个党派得票数$x$, 枚举$x$, 则对于所有票数 ...

  10. Rotate Array 旋转数组 JS 版本解法

    Given an array, rotate the array to the right by k steps, where k is non-negative. 给定一个数组,并且给定一个非负数的 ...