最近在看一个项目,其中用到异步进程——控件Invoke,这里将具体用法介绍如下:
以进度条为例:
//声明委托 delegate void SetProgressBarEnabledDelegate(ToolStripProgressBar progressBar,bool enable); //运行异步进程 this.Invoke(new SetProgressBarEnabledDelegate(SetProgressBarEnabled), new object[] { toolStripProgressBar1, p }); //所调用的方法 private void SetProgressBarEnabled(ToolStripProgressBar progressBar, bool enable) { if (!enable) { toolStripProgressBar1.Value = 0; } progressBar.Enabled = enable; }
后来查资料发现,C#中Invoke有两种,一种是控件的,一种是代理的,现将查到的区别转发如下:
c# Invoke和BeginInvoke 区别
(一)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的真正涵义"一文中的评论