C#中 Invoke和BeginInvoke的区别详解

一、Invoke和BeginInvoke方法,主要用于子线程操作主线程UI的控件,修改控件属性等。

(1)Invoke同步运行,会等待代码运行完之后返回,线程会阻塞。

(2)BeginInvoke异步运行,调用之后立即返回,不会等待修改控件代码执行完。不会阻塞。

故由上述可知,Invoke和BeginInvoke方法由ISynchronizeInvoke接口提供,且都需要一个委托对象作为参数。委托类似于回调函数的地址,调用者可通过这两个方法将需要调用的函数地址封送到界面线程。如果这些封送给界面线程的方法包含了更改界面控件的代码,由于最终执行这个方法是在界面控件线程中,从而避免了线程之间的竞争。

(3)使用Invoke方法完成委托的封送,类似于使用SendMessage方法给界面线程发送消息,为同步方法。在Invoke封装的方法未执行完毕之前,Invoke方法是不会返回,使调用者线程被阻塞。

(4)使用BeginInvoke方法完成委托的封送,类似于使用PostMessage方法给界面线程发送消息,为异步方法。在完成委托的封送后,BeginInvoke方法立即返回,不会等待委托的方法执行完毕,调用者线程将不会阻塞。但是调用者可以使用EndInvoke方法或者其它类似WaitHandle机制等待异步操作的完成。

但是,Invoke和BeginInvoke在内部的实现上都是使用PostMessage方法,从而避免SendMessage方法带来的问题。其中Invoke方法的同步阻塞是使用WaitHandle机制完成。

二、使用场合

若你的后台线程在更新UI界面且不需要等待,则应该使用BeginInvoke方法进行异步操作。

若你的后台线程在更新UI界面并且需要等待,则应该使用Invoke方法进行同步操作。

在ISynchronizeInvoke接口中,可以看到还有一个InvokeRequired。这个属性的作用是:在编程时确定一个对象在访问UI控件时是否需要使用Invoke和BeginInvoke方法进行封送,如果不需要则可以直接进行更新。在调用者对象和UI对象属于同一个线程时,该属性返回false。Control类对这一属性的实现是在判断调用者和控件是否同属于一个线程。

Delegate.BeginInvoke

通过一个委托来进行同步方法的异步调用,也是.NET提供的异步调用机制之一。但是Delegate.BeginInvoke方法是从ThreadPool中取出的一个线程来执行这个方法,以获得异步的执行效果。如果采用这种方式提交多个异步委托,这些调用的顺序无法得到保障。而且由于使用的是线程池中的线程来完成任务,若频繁的使用,会对系统的性能造成影响。

在Control类中的BeginInvoke方法没有开辟新的线程完成委托任务,而是让界面所属的控件线程完成委托任务(异步操作就是开辟新的线程的说法也不一定准确)。

Control.BeginInvoke和Control.Invoke

<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序街头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值