新閣上位機(jī)開(kāi)發(fā)--Delegate與Action,建議先看為敬
背景
很多C#上位機(jī)初學(xué)者,都遇到過(guò)這樣的問(wèn)題,今天就這個(gè)問(wèn)題,進(jìn)行分析。

根源
先說(shuō)下這個(gè)問(wèn)題產(chǎn)生的根源,大家都知道,程序運(yùn)行起來(lái)之后,首先會(huì)有一個(gè)主線程,主線程用于處理控件生成、界面渲染、事件響應(yīng)等操作,因此我們可以理解為窗體里的控件是屬于主線程的。
如果我們想實(shí)現(xiàn)與主線程同時(shí)執(zhí)行另一件事,一般會(huì)去使用多線程,因此多線程,從某種意義上來(lái)說(shuō),它和主線程的身份是平等的,就像你和你的同事的關(guān)系一樣,你們是平級(jí)的關(guān)系。如果你同事有一天想從你手上把你的項(xiàng)目程序拿過(guò)去,你愿不愿意?

所以,如果在多線程里操作主線程的控件,你覺(jué)得主線程會(huì)不會(huì)答應(yīng),當(dāng)然不會(huì),所以,它就會(huì)給你報(bào)個(gè)錯(cuò),給你一個(gè)警告!

分析
那么如何解決呢?
所以你的同事就會(huì)找到你們領(lǐng)導(dǎo),跟你們領(lǐng)導(dǎo)這樣說(shuō):我手頭上的這個(gè)100萬(wàn)的項(xiàng)目,能給公司帶來(lái)50%的利潤(rùn),現(xiàn)在需要用到他之前那個(gè)項(xiàng)目里的一個(gè)小知識(shí),需要他把程序給我參考一下。
于是,領(lǐng)導(dǎo)和你“商量”了一下,你便妥協(xié)了。
你那個(gè)同事利用的招數(shù)叫做—————委托。
現(xiàn)在多線程要干這個(gè)事,也要靠委托來(lái)做。
委托
委托定義:委托(Delegate) 是對(duì)某個(gè)方法的引用的一種引用類型變量。

那就別看了,跟著我動(dòng)手做。
1、聲明委托
委托聲明需要根據(jù)執(zhí)行的方法來(lái)定,嚴(yán)格來(lái)說(shuō),就是根據(jù)執(zhí)行方法的返回值和參數(shù),我們只是給窗體的Text設(shè)置一個(gè)固定值而已,因此我們的參數(shù)是空,返回值也為空。
聲明委托如下:
????//聲明委托
????public?delegate?void?SetFormTextDelegate();
2、創(chuàng)建委托對(duì)象
委托嚴(yán)格來(lái)說(shuō)是一種類型,就像類一樣,如果想要調(diào)用某個(gè)類,必須要?jiǎng)?chuàng)建一個(gè)該類的對(duì)象,所以我們要?jiǎng)?chuàng)建一個(gè)委托對(duì)象:
????//創(chuàng)建委托對(duì)象
????private?SetFormTextDelegate?SetFormText;
3、創(chuàng)建委托方法
委托對(duì)象也只是一個(gè)對(duì)象而已,就像領(lǐng)導(dǎo)一樣,領(lǐng)導(dǎo)是不可能干活的,最終干活還得靠底下的兵來(lái)干,所以我們還得招人去干活。
招人干活就是委托方法,我們現(xiàn)在這個(gè)活很簡(jiǎn)單,所以我們的方法也很簡(jiǎn)單。
????????//執(zhí)行方法
????????private?void?ExcuteMethod()
????????{
????????????this.Text?=?"多線程測(cè)試";
????????}
4、委托綁定
我們招到了一個(gè)“兵”,現(xiàn)在也有一個(gè)部門(mén)領(lǐng)導(dǎo),怎么把他們聯(lián)系起來(lái)呢?
很簡(jiǎn)單,讓人事把這個(gè)兵分到這個(gè)部門(mén)就行了,這個(gè)分配的過(guò)程就是委托綁定,代碼如下:
??????//委托綁定
??????this.SetFormText?=?ExcuteMethod;
5、委托調(diào)用
萬(wàn)事俱備,只欠東風(fēng),終于干活了。
作為公司的老板,一般是不可能跟員工打交道的,他會(huì)把任務(wù)分配給部門(mén)領(lǐng)導(dǎo),部門(mén)領(lǐng)導(dǎo)會(huì)把活再分配下去,所以我們委托調(diào)用,也是調(diào)用委托對(duì)象。
????????///?<summary>
????????///?多線程方法
????????///?</summary>
????????private?void?ThreadMethod()
????????{
????????????//調(diào)用委托
????????????SetFormText();
????????}
以上五步,就是委托的實(shí)現(xiàn)過(guò)程。
然而,我們運(yùn)行之后,還是會(huì)報(bào)錯(cuò)。

沒(méi)有那么簡(jiǎn)單的事!
因?yàn)橄胍诙嗑€程里操作主線程的控件,你還得經(jīng)過(guò)控件的同意,怎么經(jīng)過(guò)控件同意呢?
控件的父類Control提供了一個(gè)這樣的方法:

意思就是說(shuō),想要操作控件,必須要通過(guò)Invoke方法來(lái)實(shí)現(xiàn),Invoke方法里參數(shù)是一個(gè)委托,于是,我們只能灰溜溜地,這樣寫(xiě):

果然,按照規(guī)矩來(lái),就能達(dá)到效果:

簡(jiǎn)化
微軟從某個(gè)版本開(kāi)始,出來(lái)了Action和Lamda表達(dá)式,Action是系統(tǒng)委托,也就是說(shuō),不需要我們手動(dòng)創(chuàng)建委托了,它有個(gè)兄弟叫Func,Action沒(méi)有返回值,最多可以有16個(gè)參數(shù),F(xiàn)unc必須要有返回值,最多可以有16個(gè)參數(shù),最后一個(gè)參數(shù)表示返回值。
于是我們開(kāi)始簡(jiǎn)化:
第一步簡(jiǎn)化:用Action作為委托來(lái)創(chuàng)建
????????///?<summary>
????????///?多線程方法
????????///?</summary>
????????private?void?ThreadMethod()
????????{
????????????//創(chuàng)建委托、綁定委托
????????????Action?action?=?new?Action(ExcuteMethod);
????????????//調(diào)用委托
????????????this.Invoke(action);
????????}
????????
????????//執(zhí)行方法
????????private?void?ExcuteMethod()
????????{
????????????this.Text?=?"多線程測(cè)試";
????????}
第二步簡(jiǎn)化:委托對(duì)象只用一次,所以可以直接放到參數(shù)里
????????///?<summary>
????????///?多線程方法
????????///?</summary>
????????private?void?ThreadMethod()
????????{
????????????//創(chuàng)建委托、綁定委托、調(diào)用委托
????????????this.Invoke(new?Action(ExcuteMethod));
????????}
????????//執(zhí)行方法
????????private?void?ExcuteMethod()
????????{
????????????this.Text?=?"多線程測(cè)試";
????????}
第三步簡(jiǎn)化:用Lamda表達(dá)式代替方法
????????///?<summary>
????????///?多線程方法
????????///?</summary>
????????private?void?ThreadMethod()
????????{
????????????//創(chuàng)建委托、綁定委托、調(diào)用委托
????????????this.Invoke(new?Action(()=>
????????????{
????????????????this.Text?=?"多線程測(cè)試";
????????????}));
????????}
總結(jié)
我們所以常寫(xiě)的那行代碼,其實(shí)只是一種簡(jiǎn)寫(xiě)方式而已,委托的五步法,不管怎么簡(jiǎn)化,怎么優(yōu)化,其實(shí)本質(zhì)還是一樣,都離開(kāi)不了這五個(gè)步驟。
這就是經(jīng)典。
我是新閣上位機(jī)開(kāi)發(fā)的付老師,用我的專業(yè)成就你的夢(mèng)想。