資源描述:
《Invoke 和 BeginInvoke 的區(qū)別》由會(huì)員上傳分享,免費(fèi)在線(xiàn)閱讀,更多相關(guān)內(nèi)容在教育資源-天天文庫(kù)。
1、Invoke和BeginInvoke的區(qū)別在Invoke或者BeginInvoke的使用中無(wú)一例外地使用了委托Delegate。一、為什么Control類(lèi)提供了Invoke和BeginInvoke機(jī)制?關(guān)于這個(gè)問(wèn)題的最主要的原因已經(jīng)是dotnet程序員眾所周知的,我在此費(fèi)點(diǎn)筆墨再次記錄到自己的日志,以便日后提醒一下自己。1、windows程序消息機(jī)制WindowsGUI程序是基于消息機(jī)制的,有個(gè)主線(xiàn)程維護(hù)著一個(gè)消息泵。這個(gè)消息泵讓windows程序生生不息。WindowsGUI程序的消息循環(huán)Windows程序有個(gè)消息隊(duì)列,窗體上的
2、所有消息是這個(gè)隊(duì)列里面消息的最主要來(lái)源。這里的while循環(huán)使用了GetMessage()這個(gè)方法,這是個(gè)阻塞方法,也就是隊(duì)列為空時(shí)方法就會(huì)被阻塞,從而這個(gè)while循環(huán)停止運(yùn)動(dòng),這避免了一個(gè)程序把cpu無(wú)緣無(wú)故地耗盡,讓其它程序難以得到響應(yīng)。當(dāng)然在某些需要cpu最大限度運(yùn)動(dòng)的程序里面就可以使用另外的方法,例如某些3d游戲或者及時(shí)戰(zhàn)略游戲中,一般會(huì)使用PeekMessage()這個(gè)方法,它不會(huì)被windows阻塞,從而保證整個(gè)游戲的流暢和比較高的幀速。這個(gè)主線(xiàn)程維護(hù)著整個(gè)窗體以及上面的子控件。當(dāng)它得到一個(gè)消息,就會(huì)調(diào)用Dispat
3、chMessage方法派遣消息,這會(huì)引起對(duì)窗體上的窗口過(guò)程的調(diào)用。窗口過(guò)程里面當(dāng)然是程序員提供的窗體數(shù)據(jù)更新代碼和其它代碼。2、dotnet里面的消息循環(huán)publicstaticvoidMain(string[]args){Formf=newForm();Application.Run(f);}Dotnet窗體程序封裝了上述的while循環(huán),這個(gè)循環(huán)就是通過(guò)Application.Run方法啟動(dòng)的。3、線(xiàn)程外操作GUI控件的問(wèn)題如果從另外一個(gè)線(xiàn)程操作windows窗體上的控件,就會(huì)和主線(xiàn)程產(chǎn)生競(jìng)爭(zhēng),造成不可預(yù)料的結(jié)果,甚至死鎖。因
4、此windowsGUI編程有一個(gè)規(guī)則,就是只能通過(guò)創(chuàng)建控件的線(xiàn)程來(lái)操作控件的數(shù)據(jù),否則就可能產(chǎn)生不可預(yù)料的結(jié)果。因此,dotnet里面,為了方便地解決這些問(wèn)題,Control類(lèi)實(shí)現(xiàn)了ISynchronizeInvoke接口,提供了Invoke和BeginInvoke方法來(lái)提供讓其它線(xiàn)程更新GUI界面控件的機(jī)制。publicinterfaceISynchronizeInvoke{[HostProtection(SecurityAction.LinkDemand,Synchronization=true,ExternalThreadi
5、ng=true)]IAsyncResultBeginInvoke(Delegatemethod,object[]args);objectEndInvoke(IAsyncResultresult);objectInvoke(Delegatemethod,object[]args);boolInvokeRequired{get;}}}如果從線(xiàn)程外操作windows窗體控件,那么就需要使用Invoke或者BeginInvoke方法,通過(guò)一個(gè)委托把調(diào)用封送到控件所屬的線(xiàn)程上執(zhí)行。二、消息機(jī)制---線(xiàn)程間和進(jìn)程間通信機(jī)制1、window消息
6、發(fā)送Windows消息機(jī)制是windows平臺(tái)上的線(xiàn)程或者進(jìn)程間通信機(jī)制之一。Windows消息值其實(shí)就是定義的一個(gè)數(shù)據(jù)結(jié)構(gòu),最重要的是消息的類(lèi)型,它就是一個(gè)整數(shù);然后就是消息的參數(shù)。消息的參數(shù)可以表示很多東西。Windows提供了一些api用來(lái)向一個(gè)線(xiàn)程的消息隊(duì)列發(fā)送消息。因此,一個(gè)線(xiàn)程可以向另一個(gè)線(xiàn)程的消息隊(duì)列發(fā)送消息從而告訴對(duì)方做什么,這樣就完成了線(xiàn)程間的通信。有些api發(fā)送消息需要一個(gè)窗口句柄,這種函數(shù)可以把消息發(fā)送到指定窗口的主線(xiàn)程消息隊(duì)列;而有些則可以直接通過(guò)線(xiàn)程句柄,把消息發(fā)送到該線(xiàn)程消息隊(duì)列中。用消息機(jī)制通信Sen
7、dMessage是windowsapi,用來(lái)把一個(gè)消息發(fā)送到一個(gè)窗口的消息隊(duì)列。這個(gè)方法是個(gè)阻塞方法,也就是操作系統(tǒng)會(huì)確保消息的確發(fā)送到目的消息隊(duì)列,并且該消息被處理完畢以后,該函數(shù)才返回。返回之前,調(diào)用者將會(huì)被暫時(shí)阻塞。PostMessage也是一個(gè)用來(lái)發(fā)送消息到窗口消息隊(duì)列的api函數(shù),但這個(gè)方法是非阻塞的。也就是它會(huì)馬上返回,而不管消息是否真的發(fā)送到目的地,也就是調(diào)用者不會(huì)被阻塞。2、InvokeandBeginInvokeInvokeorBeginInvokeInvoke或者BeginInvoke方法都需要一個(gè)委托對(duì)象作為
8、參數(shù)。委托類(lèi)似于回調(diào)函數(shù)的地址,因此調(diào)用者通過(guò)這兩個(gè)方法就可以把需要調(diào)用的函數(shù)地址封送給界面線(xiàn)程。這些方法里面如果包含了更改控件狀態(tài)的代碼,那么由于最終執(zhí)行這個(gè)方法的是界面線(xiàn)程,從而避免了競(jìng)爭(zhēng)條件,避免了不可預(yù)料的問(wèn)題。如果其它線(xiàn)程直接操作界面線(xiàn)程