c# Invoke和BeginInvoke

***************************************************

更多精彩,欢迎进入:http://shop115376623.taobao.com

***************************************************


转自:http://blog.3snews.net/html/30/34530-27563.html

在多线程编程中,我们经常要在工作线程中去更新界面显示,而在多线程中直接调用界面控件的方法 是错误的做法,Invoke 和 BeginInvoke 就是为了解决这个问题而出现的,使你在多线程中安全的更新界面显示。

正确的做法是将工作线程中涉及更新界面的代码封装为一个方法,通过 Invoke 或者 BeginInvoke 去调用,两者的区别就是一个导致工作线程等待,而另外一个则不会。

而所谓的“一面响应操作,一面添加节点”永远只能是相对的,使 UI 线程的负担不至于太大而已,因为界面的正确更新始终要通过 UI 线程去做,我们要做的事情是在工作线程中包揽大部分的运算,而将对纯粹的界面更新放到 UI 线程中去做,这样也就达到了减轻 UI 线程负担的目的了。

举个简单例子说明下使用方法,比如你在启动一个线程,在线程的方法中想更新窗体中的一个TextBox.. 

using System.Threading; 

//启动一个线程 
Thread thread=new Thread(new ThreadStart(DoWork)); 
thread.Start(); 

//线程方法 
private void DoWork() 

this.TextBox1.Text="我是一个文本框"; 


如果你像上面操作,在VS2005或2008里是会有异常的... 

正确的做法是用Invoke\BeginInvoke

using System.Threading;
namespace test
{
public partial class Form1 : Form
{
public delegate void MyInvoke(string str1,string str2);
public Form1()
{
InitializeComponent();


}
public void DoWork()
{
MyInvoke mi = new MyInvoke(UpdateForm);
this.BeginInvoke(mi, new Object[] {"我是文本框","haha"});
}
public void UpdateForm(string param1,string parm2)
{
this.textBox1.Text = param1+parm2;
}
private void button1_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(DoWork));
thread.Start();
}
}
}

注意代理的使用!

//

c# Invoke和BeginInvoke 区别


转自http://www.cnblogs.com/c2303191/articles/826571.html

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

Control.BeginInvoke 方法 (Delegate) :在创建控件的基础句柄所在线程上异步执行指定委托。

(一)Control的Invoke和BeginInvoke
我们要基于以下认识:
(1)Control的Invoke和BeginInvoke与Delegate的Invoke和BeginInvoke是不同的。
(2)Control的Invoke和BeginInvoke的参数为delegate,委托的方法是在Control的线程上执行的,也就是我们平时所说的UI线程。

我们以代码(一)来看(Control的Invoke)
private delegate void InvokeDelegate();
private void InvokeMethod(){
   //C代码段
}
private void butInvoke_Click(object sender, EventArgs e) {
   //A代码段.......
   this.Invoke(new InvokeDelegate(InvokeMethod));
   //B代码段......
}
你觉得代码的执行顺序是什么呢?记好Control的Invoke和BeginInvoke都执行在主线程即UI线程上
A------>C---------------->B
解释:(1)A在UI线程上执行完后,开始Invoke,Invoke是同步
(2)代码段B并不执行,而是立即在UI线程上执行InvokeMethod方法,即代码段C。
(3)InvokeMethod方法执行完后,代码段C才在UI线程上继续执行。

看看代码(二),Control的BeginInvoke
private delegate void BeginInvokeDelegate();
private void BeginInvokeMethod(){
   //C代码段
}
private void butBeginInvoke_Click(object sender, EventArgs e) {
   //A代码段.......
   this.BeginInvoke(new BeginInvokeDelegate(BeginInvokeMethod));
   //B代码段......
}

你觉得代码的执行顺序是什么呢?记好Control的Invoke和BeginInvoke都执行在主线程即UI线程上
A----------->B--------------->C慎重,这个只做参考。。。。。,我也不肯定执行顺序,如果有哪位达人知道的话请告知。
解释::(1)A在UI线程上执行完后,开始BeginInvoke,BeginInvoke是异步
(2)InvokeMethod方法,即代码段C不会执行,而是立即在UI线程上执行代码段B。
(3)代码段B执行完后(就是说butBeginInvoke_Click方法执行完后),InvokeMethod方法,即代码段C才在UI线程上继续执行。

由此,我们知道:
Control的Invoke和BeginInvoke的委托方法是在主线程,即UI线程上执行的。也就是说如果你的委托方法用来取花费时间长的数据,然后更新界面什么的,千万别在UI线程上调用Control.Invoke和Control.BeginInvoke,因为这些是依然阻塞UI线程的,造成界面的假死。

那么,这个异步到底是什么意思呢?

异步是指相对于调用BeginInvoke的线程异步,而不是相对于UI线程异步,你在UI线程上调用BeginInvoke ,当然不行了。----摘自"Invoke和BeginInvoke的真正涵义"一文中的评论。
BeginInvoke的原理是将调用的方法Marshal成消息,然后调用Win32 API中的RegisterWindowMessage()向UI窗口发送消息。----摘自"Invoke和BeginInvoke的真正涵义"一文中的评论。

(二)我们用Thread来调用BeginInvoke和Invoke
      我们开一个线程,让线程执行一些耗费时间的操作,然后再用Control.Invoke和Control.BeginInvoke回到用户UI线程,执行界面更新。

代码(三)  Thread调用Control的Invoke
private Thread invokeThread;
private delegate void invokeDelegate();
private void StartMethod(){
   //C代码段......
   Control.Invoke(new invokeDelegate(invokeMethod));
  //D代码段......
}
private void invokeMethod(){
  //E代码段
}
private void butInvoke_Click(object sender, EventArgs e) {
   //A代码段.......
   invokeThread = new Thread(new ThreadStart(StartMethod));
   invokeThread.Start();
   //B代码段......
}

你觉得代码的执行顺序是什么呢?记好Control的Invoke和BeginInvoke都执行在主线程即UI线程上
A------>(Start一开始B和StartMethod的C就同时执行)---->(C执行完了,不管B有没有执行完,invokeThread把消息封送(invoke)给UI线程,然后自己等待)---->UI线程处理完butInvoke_Click消息后,处理invokeThread封送过来的消息,执行invokeMethod方法,即代码段E,处理往后UI线程切换到invokeThread线程。
这个Control.Invoke是相对于invokeThread线程同步的,阻止了其运行。

解释:
1。UI执行A
2。UI开线程InvokeThread,B和C同时执行,B执行在线程UI上,C执行在线程invokeThread上。
3。invokeThread封送消息给UI,然后自己等待,UI处理完消息后,处理invokeThread封送的消息,即代码段E
4。UI执行完E后,转到线程invokeThread上,invokeThread线程执行代码段D

代码(四)  Thread调用Control的BeginInvoke
private Thread beginInvokeThread;
private delegate void beginInvokeDelegate();
private void StartMethod(){
   //C代码段......
   Control.BeginInvoke(new beginInvokeDelegate(beginInvokeMethod));
  //D代码段......
}
private void beginInvokeMethod(){
  //E代码段
}
private void butBeginInvoke_Click(object sender, EventArgs e) {
   //A代码段.......
   beginInvokeThread = new Thread(new ThreadStart(StartMethod));
   beginInvokeThread .Start();
   //B代码段......
}
你觉得代码的执行顺序是什么呢?记好Control的Invoke和BeginInvoke都执行在主线程即UI线程上
A在UI线程上执行----->beginInvokeThread线程开始执行,UI继续执行代码段B,并发地invokeThread执行代码段C-------------->不管UI有没有执行完代码段B,这时beginInvokeThread线程把消息封送给UI,单自己并不等待,继续向下执行-------->UI处理完butBeginInvoke_Click消息后,处理beginInvokeThread线程封送过来的消息。


解释:
1。UI执行A
2。UI开线程beginInvokeThread,B和C同时执行,B执行在线程UI上,C执行在线程beginInvokeThread上。
3。beginInvokeThread封送消息给UI,然后自己继续执行代码D,UI处理完消息后,处理invokeThread封送的消息,即代码段E
有点疑问:如果UI先执行完毕,是不是有可能过了段时间beginInvokeThread才把消息封送给UI,然后UI才继续执行封送的消息E。如图浅绿的部分。


Control的BeginInvoke是相对于调用它的线程,即beginInvokeThread相对是异步的。
因此,我们可以想到。如果要异步取耗费长时间的数据,比如从数据库中读大量数据,我们应该这么做。
(1)如果你想阻止调用线程,那么调用代码(三),代码段D删掉,C改为耗费长时间的操作,因为这个操作是在另外一个线程中做的。代码段E改为更新界面的方法。
(2)如果你不想阻止调用线程,那么调用代码(四),代码段D删掉,C改为耗费长时间的操作,因为这个操作是在另外一个线程中做的。代码段E改为更新界面的方法。



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/459053.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle手边常用70则脚本知识汇总

Oracle手边常用70则脚本知识汇总 作者:白宁超 时间:2016年3月4日13:58:36 摘要: 日常使用oracle数据库过程中,常用脚本命令莫不是用户和密码、表空间、多表联合、执行语句等常规操作。另外表的导入导出也很常用,这些脚步命令之前都…

php常见的面试题目

一. 基本知识点1.1 HTTP协议中几个状态码的含义:503 500 401 403 404 200 301 302。。。200 : 请求成功,请求的数据随之返回。301 : 永久性重定向。302 : 暂时行重定向。401 : 当前请求需要用户验证。403 : 服务器拒绝执行请求,即没有权限。404 : 请求失…

VS2010断点设置技巧

*************************************************** 更多精彩,欢迎进入:http://shop115376623.taobao.com *************************************************** 许多Visual Studio下的程序员,甚至一些很有经验的开发人员,都不…

IOS应用开发版本控制工具之Versions使用,iosversions

Versions版本控制工具破解版(Versions.zip)下载请见本博文附件。下载后在MAC安装完以后,图标是莲花状。见下图: 双击运行如下图: 点击Repository,连接SVN服务器Repository(服务器端采用的是SVN服…

如何在多web服务器共享SESSION数据

2019独角兽企业重金招聘Python工程师标准>>> 一、问题起源 稍大一些的网站,通常都会有好几个服务器,每个服务器运行着不同功能的模块,使用不同的二级域名,而一个整体性强的网站,用户系统是统一的&#xff0…

grpc php 返回值过大,使用grpc实现php、java、go三方互调

grpc作为经典的rpc协议,虽然略重,但是是有学习的价值的通过下面的内容可以快速上手这个grpc框架安装命令行工具php需要这个额外的protoc、grpc_php_plugin工具把这个protobuf格式的文件生成php语言里的类go需要安装protoc-gen-go工具把protobuf格式的接口…

SOCKET通信的基本步骤

SOCKET通信的基本步骤 1)建立一个服务器ServerSocket,并同时定义好ServerSocket的监听端口;2)ServerSocket 调用accept()方法,使之处于阻塞。3)创建一个客户机Socket,并设置好服务器的IP和端口。4&#xff…

Linux epoll 笔记(高并发事件处理机制)

wiki: Epoll优点; Epoll工作流程; Epoll实现机制: epollevent; Epoll源码分析; Epoll接口: epoll_create; epoll_ctl; epoll_close; Epoll工作方式: LT(level-triggered); ET(edge-triggered); Epoll应用模式; Epoll优点&#xff…

matlab 作图 虚线太长,matlab 极坐标绘图 在matlab中,用polar画的图形,如何使虚线圆多显示几个?...

满意答案iredwood推荐于 2018.12.26采纳率:52% 等级:12已帮助:13535人打开polar.m 文件,路径可通过输入 which polar 命令得到。其中修改下面这段代码,可以控制虚线圆的显示个数。其中rticks 为控制显示个数的参量。…

《学习opencv》笔记——矩阵和图像处理——cvAnd、cvAndS、cvAvg and cvAvgSdv

矩阵和图像的操作 (1)cvAnd函数 其结构 void cvAnd( //将src1和src2按像素点取“位与运算”const CvArr* src1,//第一个矩阵const CvArr* src2,//第二个矩阵CvArr* dst,//结果矩阵const CvArr* mask NULL;//矩阵经行像素点与的“开关” );程序实例#include <cv.h> #inc…

Hibernate之加载策略(延迟加载与即时加载)和抓取策略(fetch)

假设现在有Book和Category两张表,表的关系为双向的一对多,表结构如下: 假设现在我想查询id为2的那本书的书名,使用session.get(...)方法: 1 Session sessionHibernateUtil.getSession(); 2 Book book (Book) session.get(Book.class,2); 3 System.out.println(book.getName());…

php多人点餐可以看到对方点的菜,千万不要小看你身边那个会点菜的人,因为

饭局上&#xff0c;你常常是负责点菜的那个人&#xff0c;还是只负责吃&#xff1f;拿起菜单点菜&#xff0c;你是很从容&#xff0c;还是不知道怎么点&#xff1f;事实上&#xff0c;饭局上那个会点菜的人&#xff0c;千万不能小看。某次随老板外出开会&#xff0c;跟去的几个…

gvim for php,转 : Gvim建立IDE编程环境 (Windows篇)

说明&#xff1a;本文是作者在完全按照著名的《手把手教你把Vim改装成一个IDE编程环境》一文&#xff0c;在Windows XP上用gvim建立IDE环境时所作的备忘。原作地址&#xff1a;http://blog.csdn.net/wooin/archive/2007/10/31/1858917.aspx。1.安装gvim7.2。运行gvim72.exe&…

阿里云使用笔记-Lrzsz上传下载文件-centos7

2019独角兽企业重金招聘Python工程师标准>>> 上传文件时提示&#xff1a; -bash: rz: command not found rz命令没找到&#xff1f; 执行sz&#xff0c;同样也没找到。 原来是要安装个叫 lrzsz 的东西&#xff0c;一查可以直接yum。 安装lrzsz&#xff1a;# yum -y …

C#中的DBNull、Null、String.Empty和“”

null可赋值任何变量,将变量置为空 DBNull只用于DataRow对象,表示数据库中的空值 String.Empty是0长度字串 Convert.IsDBNull判断是否为DBNull DBNull.Value与Null的区别 Null是.net中无效的对象引用。 DBNull是一个类。DBNull.Value是它唯一的实例。它指数据库中数据为空(&l…

iOS开发--验证码

第一步&#xff0c;拖两个空间textfiled和button到storyboard上的viewcontroller上。 第二步&#xff0c;拖线&#xff0c;链接到.h文件中代码如下&#xff1a; 1property (weak, nonatomic) IBOutlet UIButton *l_timeButton;第三步&#xff0c;在,m文件中为l_timeButton设置监…

C# Socket 编程详解

Microsoft.Net Framework为应用程序访问Internet提供了分层的、可扩展的以及受管辖的网络服务&#xff0c;其名字空间System.Net和 System.Net.Sockets包含丰富的类可以开发多种网络应用程序。.Net类采用的分层结构允许应用程序在不同的控制级别上访问网络&#xff0c;开发人员…

TCP/ip通信模式

TCP/IP 应用层与应用程序*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** 文档出处&#xff1a;http://blog.csdn.net/bingxx11/article…

8 Regular Expressions You Should Know

2019独角兽企业重金招聘Python工程师标准>>> Regular expressions are a language of their own. When you learn a new programming language, theyre this little sub-language that makes no sense at first glance. Many times you have to read another tutori…

poj 3278 catch that cow BFS(基础水)

Catch That CowTime Limit: 2000MS Memory Limit: 65536KTotal Submissions: 61826 Accepted: 19329Description Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a num…