至于要用到題目說(shuō)到的這種方法,大概是因為在程序執行一些耗時(shí)的操作的時(shí)候,為了使得界面上不至于處于卡死狀態(tài),就讓這些耗時(shí)的操作放在一邊慢慢執行,并用一些方法來(lái)監視這些工作執行的狀態(tài)。在這個(gè)過(guò)程中我的主線(xiàn)程可以完成一些其他的工作,這叫磨刀不誤砍柴工··嘿嘿
關(guān)于異步委托,這里要用到里面的兩個(gè)方法BeginInvoke 和 EndInvoke
BeginInvoke 方法啟動(dòng)異步調用。 該方法與您需要異步執行的方法具有相同的參數,還有另外兩個(gè)可選參數。 第一個(gè)參數是一個(gè) AsyncCallback 委托,該委托引用在異步調用完成時(shí)要調用的方法。 第二個(gè)參數是一個(gè)用戶(hù)定義的對象,該對象將信息傳遞到回調方法。 BeginInvoke 立即返回,不等待異步調用完成。 BeginInvoke 返回一個(gè) IAsyncResult,后者可用于監視異步調用的進(jìn)度。
用代碼講解貌似簡(jiǎn)單一點(diǎn)·來(lái)一個(gè)三國·長(cháng)坂坡
- class Program
- {
-
- #region 三國·長(cháng)板坡
- //定義一個(gè)委托類(lèi)型
- public delegate int TaskDelegate(object obj, int ms);
-
-
- //定義一個(gè)靜態(tài)方法 看這個(gè)方法的開(kāi)頭就知道,大概是委托將要調用的方法
- public static int ForFun(object obj, int ms)
- {
- Thread t = Thread.CurrentThread;
- t.Name = "張飛";
- Console.WriteLine("我有{0}在手,誰(shuí)敢與我{1}大戰三百回合", obj.ToString(), t.Name);
- Thread.Sleep(ms);
- return 1234;
- }
-
- //主線(xiàn)程入口,這個(gè)也是我們的主要戰場(chǎng)
- static void Main(string[] args)
- {
- Thread t1 = Thread.CurrentThread;
- t1.Name = "長(cháng)坂坡";
-
-
- //主公的任務(wù)
- Console.WriteLine("趕緊去{0}把趙子龍和阿斗救回來(lái)", t1.Name);
-
-
- //為剛才委托指定方法,這里注意方法只需要提供方法名字就可以
- TaskDelegate t = ForFun;
- //使用委托的BeginIvoke方法為所委托耳方法賦值,并將執行結果交給IAsysResult接口
- IAsyncResult ir = t.BeginInvoke("青釭劍", 1000 * new Random().Next(5), null, null);//new Random().Next(5) 返回一個(gè)小于所指定最大值的非負隨機數
- //上面這個(gè)函數除了最后兩個(gè)參數之前的參數都是那個(gè)委托方法需要的參數
-
- //曹操的軍隊比想象中快
- Thread.Sleep(2000);
- int i = 0;//計數器
-
- // 如果委托還沒(méi)有執行完就開(kāi)始循環(huán)
- while (!ir.IsCompleted)
- {
- i++;
- Console.WriteLine(i.ToString());
- Thread.Sleep(100);
- }
- //獲取委托方法執行以后的返回值
- int result = t.EndInvoke(ir);
-
- Console.WriteLine("報告主公,曹軍殺來(lái),我?jiàn)^力拼殺,斬敵{0}人", i.ToString());
-
- if (i > 1)
- {
- Console.WriteLine("辛苦飛哥了,你殺敵{0}人,應該獎勵黃金{1}兩", i.ToString(), (i * 100).ToString());
-
- }
- else
- {
- Console.WriteLine("既然是未有殺敵,那今天就不獎勵你啦");
- }
- Console.Read();
- }
1用IAsyncResult中的IsCompleted 屬性進(jìn)行輪詢(xún)判斷是否完成
2 BeginInvoke()的函數聲明:
public IAsyncResult BeginInvoke(
<輸入和輸出變量>,回調函數callback , 附加信息AsyncState)
3 函數返回值類(lèi)型:
public interface IAsyncResult
{
object AsyncState{ get;} //如果有回調函數的話(huà)該參數用于保存要傳遞給回調函數的參數值
WaitHandle AsyncWaitHandle{ get;}
bool CompletedSynchronously{ get;}
bool IsCompleted{ get;} //保存方法是否執行結束,我們可以通過(guò)該屬性的值來(lái)判斷異步方法是否執行結束
}
4 EndInvoke方法用于檢索異步調用結果。方法聲明:
public <方法返回值類(lèi)型>EndInvoke(<聲明為ref或out的參數>, IAsyncResult result )
5 EndInvoke 方法檢索異步調用的結果。 在調用 BeginInvoke 之后隨時(shí)可以調用該方法。 如果異步調用尚未完成,則 EndInvoke 會(huì )一直阻止調用線(xiàn)程,直到異步調用完成。
上面這個(gè)例子就是:使用輪詢(xún)等待異步調用完成:使用IAsyncResult的IsCompleted屬性來(lái)判斷異步調用是否完成(
–IAsyncResult來(lái)檢測
)
下面在循環(huán)部分修改代碼就得到了異步通信的第二種方法:使用與IAsyncResult相關(guān)的等待句柄
- // 如果委托還沒(méi)有執行完就開(kāi)始循環(huán)
- while (!ir.IsCompleted)
- {
- i++;
- Console.WriteLine(i.ToString());
- if(ir.AsyncWaitHandle.WaitOne(100,true))
- {
- Console.WriteLine("主公的救兵怎么還不到,老張我撐不住了");
- break;
- }
- // Thread.Sleep(100);
- }
使用 IAsyncResult.AsyncWaitHandle 屬性獲取 WaitHandle,使用其 WaitOne 方法阻止執行,直至 WaitHandle 收到信號,然后調用 EndInvoke。
第三種異步委托的方法就是使用回調函數
那就先寫(xiě)一個(gè)回調函數來(lái)使用······要注意回調函數一定是在輔助線(xiàn)程里面使用
- static void TakesWhileCompleted(IAsyncResult ar)
- {
- //如果為空則拋出異常
- if (ar == null)
- throw new ArgumentNullException("ar");
- //將ar對象中IAsyncResult屬性強類(lèi)型為T(mén)askDelegate委托類(lèi)型
- TaskDelegate dl = ar.AsyncState as TaskDelegate;
- //跟蹤檢查dl是否有效,如果無(wú)效則顯示提示消息
- System.Diagnostics.Trace.Assert(dl != null, "無(wú)效的對象類(lèi)型");
- //執行委托方法,并將結果交給變量Result
- int result = dl.EndInvoke(ar);
- //打印結果,這里顯示方法“ForFun”所返回的值
- Console.WriteLine("老張我英勇非常,殺敵{0}人", result);
- }
回調函數部分未完待續·····