WinForm 异步调用方法
假如要在一個(gè)線程中異步執(zhí)行一個(gè)方法,則先創(chuàng)建一個(gè)該方法的委托類型,然后CLR會(huì)自動(dòng)為該委托類型定義一個(gè)BeginInvoke方法和EndInvoke方法,我們就靠這兩個(gè)方法異步調(diào)用委托類型指向的方法(這句話有點(diǎn)繞口,呵呵)
BeginInvoke這個(gè)方法用于啟動(dòng)異步調(diào)用,該方法具有和要異步執(zhí)行的方法具有相同的參數(shù)列表,只不過又多加了兩個(gè)參數(shù),多加的那兩個(gè)參數(shù)的作用在后面介紹。執(zhí)行BeginInvoke方法后,將立即返回一個(gè)IAsyncResult,用于監(jiān)視被調(diào)用方法執(zhí)行的進(jìn)度。
EndInvoke這個(gè)方法用于得到異步調(diào)用的結(jié)果,調(diào)用BeginInvoke方法后隨時(shí)可以調(diào)用EndInvoke方法,假如異步調(diào)用還沒有完成,EndInvoke會(huì)阻塞到異步調(diào)用執(zhí)行完畢,EndInvoke的參數(shù)包括被調(diào)用方法的out和ref參數(shù),還有在調(diào)用BeginInvoke方法時(shí)得到的那個(gè)IAsyncResult(好像就是一個(gè)哈希表的key,可以靠這個(gè)key去得到相應(yīng)的線程,這樣就可以處理多線程而不至于混亂了)
第一種方法:使用BeginInvoke方法后,主線程去執(zhí)行一些操作,然后再使用EndInvoke方法等待被調(diào)用方法完成,以下是示例代碼
?
using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace sample {class AsyncDemo // 我定義了一個(gè)演示的類,里面有一個(gè)測(cè)試方法TestMethod 其實(shí)完全可以把這個(gè)TestMethod寫到Main()函數(shù)的同一個(gè)類中,只不過寫成static方法即可{public string TestMethod(int callDuration, out int threadid){Console.WriteLine("Test Method begins");Thread.Sleep(callDuration);//睡眠callDuration指定的毫秒threadid = AppDomain.GetCurrentThreadId();//獲取當(dāng)前線程的idreturn "MyCallTime was" + callDuration.ToString();//返回當(dāng)前線程睡眠的時(shí)間}}public delegate string AsyncDelegate(int callDuration, out int threadid); //創(chuàng)建一個(gè)AsyncDemo類中TestMethod方法相同簽名的委托類型class Program{static void Main(string[] args){int threadID;AsyncDemo ad = new AsyncDemo();//聲明一個(gè)AsyncDemo類型的對(duì)象ad,并創(chuàng)建一個(gè)實(shí)例賦給它AsyncDelegate andl = new AsyncDelegate(ad.TestMethod);//聲明一個(gè)AsyncDelegate類型的對(duì)象andl,并讓他指向ad對(duì)象的TestMethod方法IAsyncResult ar = andl.BeginInvoke(3000, out threadID, null, null);//執(zhí)行andl的BeginInvoke方法,返回一個(gè)IAsyncResult類型的實(shí)例對(duì)象給ar變量,其實(shí)是一個(gè)號(hào)碼牌(不知道這樣說是否形象)Thread.Sleep(10);//使當(dāng)前線程睡眠10毫秒(其實(shí)可去掉這句,我寫這個(gè)的目的是確保異步線程已啟動(dòng),再執(zhí)行以下語句)Console.WriteLine("Main Thread {0} Does Some Work",AppDomain.GetCurrentThreadId());//輸出當(dāng)前線程的idstring ret = andl.EndInvoke(out threadID, ar);//使用EndInvoke方法,傳入out或ref類型參數(shù)和在調(diào)用BeginInvoke方法時(shí)得到的IAsyncResult,此時(shí)主線程將等待異步調(diào)用執(zhí)行完畢,返回結(jié)果后執(zhí)行以下語句Console.WriteLine("The call executed on thread {0},with return value : {1}",threadID, ret);Console.ReadLine();}} }ok,以上是第一種直接使用EndInvoke來等待異步調(diào)用完成的方法 ================================================ ================================================第二種方法是借助返回的IAsyncHandle的WaitHandle屬性的WaitOne()方法實(shí)現(xiàn)線程同步后,執(zhí)行代碼,然后將要執(zhí)行的代碼執(zhí)行后隨時(shí)可調(diào)用EndInvoke方法。示例代碼基本沒有什么改動(dòng),只是在BeginInvoke方法后執(zhí)行一個(gè)ar.WaitHandle.WaitOne()方法,該方法將阻塞主線程使主線程等待返回ar的begininvoke調(diào)用的方法的線程執(zhí)行完畢(不要怪我說話有點(diǎn)繞,我是說的詳細(xì),否則你弄不明白,仔細(xì)看這句話就明白了^o^)。本著一切代碼都是紙老虎的原則,請(qǐng)仔細(xì)分析下面的代碼 其實(shí)和示例1基本無異 ,只是使用WaitOne()方法同步了一下線程而已using System; using System.Collections.Generic; using System.Text; using System.Threading; namespace sample {class AsyncDemo{public string TestMethod(int callDuration, out int threadid){Console.WriteLine("Test Method begins");Thread.Sleep(callDuration);threadid = AppDomain.GetCurrentThreadId();return "MyCallTime was" + callDuration.ToString();}}public delegate string AsyncDelegate(int callDuration, out int threadid);class Program{static void Main(string[] args){int threadID;AsyncDemo ad = new AsyncDemo();AsyncDelegate andl = new AsyncDelegate(ad.TestMethod);IAsyncResult ar = andl.BeginInvoke(3000, out threadID, null, null);Thread.Sleep(10);Console.WriteLine("Main Thread {0} Does Some Work",AppDomain.GetCurrentThreadId());ar.AsyncWaitHandle.WaitOne();//執(zhí)行該方法時(shí)主線程將等待輔助線程執(zhí)行完畢,使兩線程同步后再執(zhí)行以下語句Console.WriteLine("其實(shí)很簡(jiǎn)單");//執(zhí)行一些方法string ret = andl.EndInvoke(out threadID, ar);//使用EndInvoke來獲取返回結(jié)果和傳入ref和out的變量獲取修改后的實(shí)例的位置(這我就不太好用語言來表述了,你自己心領(lǐng)神會(huì)吧)Console.WriteLine("The call executed on thread {0},with return value : {1}",threadID, ret);Console.ReadLine();}} }
?
總結(jié)
以上是生活随笔為你收集整理的WinForm 异步调用方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 11月份是个少产的季节
- 下一篇: JSP- 内置对象