C#異步編程模式IAsyncResult淺析
C#異步編程模式IAsyncResult概述
IAsyncResult 異步設(shè)計(jì)模式通過名為 BeginOperationName 和 EndOperationName 的兩個(gè)方法來實(shí)現(xiàn)原同步方法的異步調(diào)用,如 FileStream 類提供了 BeginRead 和 EndRead 方法來從文件異步讀取字節(jié),它們是 Read 方法的異步版本
Begin 方法包含同步方法簽名中的任何參數(shù),此外還包含另外兩個(gè)參數(shù):一個(gè)AsyncCallback 委托和一個(gè)用戶定義的狀態(tài)對(duì)象。委托用來調(diào)用回調(diào)方法,狀態(tài)對(duì)象是用來向回調(diào)方法傳遞狀態(tài)信息。該方法返回一個(gè)實(shí)現(xiàn) IAsyncResult 接口的對(duì)象
End 方法用于結(jié)束異步操作并返回結(jié)果,因此包含同步方法簽名中的 ref 和 out 參數(shù),返回值類型也與同步方法相同。該方法還包括一個(gè) IAsyncResult 參數(shù),用于獲取異步操作是否完成的信息,當(dāng)然在使用時(shí)就必須傳入對(duì)應(yīng)的 Begin 方法返回的對(duì)象實(shí)例
開始異步操作后如果要阻止應(yīng)用程序,可以直接調(diào)用 End 方法,這會(huì)阻止應(yīng)用程序直到異步操作完成后再繼續(xù)執(zhí)行。也可以使用 IAsyncResult 的 AsyncWaitHandle 屬性,調(diào)用其中的WaitOne等方法來阻塞線程。這兩種方法的區(qū)別不大,只是前者必須一直等待而后者可以設(shè)置等待超時(shí)
如果不阻止應(yīng)用程序,則可以通過輪循 IAsyncResult 的 IsCompleted 狀態(tài)來判斷操作是否完成,或使用 AsyncCallback 委托來結(jié)束異步操作。AsyncCallback 委托包含一個(gè) IAsyncResult 的簽名,回調(diào)方法內(nèi)部再調(diào)用 End 方法來獲取操作執(zhí)行結(jié)果
C#異步編程模式IAsyncResult之IAsyncResult 接口
- public interface IAsyncResult
- {
- object AsyncState { get; }
- WaitHandle AsyncWaitHandle { get; }
- bool CompletedSynchronously { get; }
- bool IsCompleted { get; }
- }
我用一個(gè) AsyncDemo 類作為異步方法的提供者,后面的程序都會(huì)調(diào)用它。內(nèi)部很簡單,構(gòu)造函數(shù)接收一個(gè)字符串作為 name ,Run 方法輸出 "My name is " + name ,而異步方法直接用委托的 BeginInvoke 和 EndInvoke 方法實(shí)現(xiàn)
- public class AsyncDemo
- {
- // Use in asynchronous methods
- private delegate string runDelegate();
- private string m_Name;
- private runDelegate m_Delegate;
- public AsyncDemo(string name)
- {
- m_Name = name;
- m_Delegate = new runDelegate(Run);
- }
- /**//// ﹤summary﹥
- /// Synchronous method
- /// ﹤/summary﹥
- /// ﹤returns﹥﹤/returns﹥
- public string Run()
- {
- return "My name is " + m_Name;
- }
- /**//// ﹤summary﹥
- /// Asynchronous begin method
- /// ﹤/summary﹥
- /// ﹤param name="callBack"﹥﹤/param﹥
- /// ﹤param name="stateObject"﹥﹤/param﹥
- /// ﹤returns﹥﹤/returns﹥
- public IAsyncResult BeginRun(
- AsyncCallback callBack, Object stateObject)
- {
- try
- {
- return m_Delegate.BeginInvoke(callBack, stateObject);
- }
- catch(Exception e)
- {
- // Hide inside method invoking stack
- throw e;
- }
- }
- /**//// ﹤summary﹥
- /// Asynchronous end method
- /// ﹤/summary﹥
- /// ﹤param name="ar"﹥﹤/param﹥
- /// ﹤returns﹥﹤/returns﹥
- public string EndRun(IAsyncResult ar)
- {
- if (ar == null)
- throw new NullReferenceException(
- "Arggument ar can't be null");
- try
- {
- return m_Delegate.EndInvoke(ar);
- }
- catch (Exception e)
- {
- // Hide inside method invoking stack
- throw e;
- }
- }
- }
C#異步編程模式IAsyncResult操作步驟:首先是 Begin 之后直接調(diào)用 End 方法,當(dāng)然中間也可以做其他的操作
- class AsyncTest
- {
- static void Main(string[] args)
- {
- AsyncDemo demo = new AsyncDemo("jiangnii");
- // Execute begin method
- IAsyncResult ar = demo.BeginRun(null, null);
- // You can do other things here
- // Use end method to block thread
- // until the operation is complete
- string demoName = demo.EndRun(ar);
- Console.WriteLine(demoName);
- }
- }
也可以用 IAsyncResult 的 AsyncWaitHandle 屬性,我在這里設(shè)置為1秒超時(shí)
- class AsyncTest
- {
- static void Main(string[] args)
- {
- AsyncDemo demo = new AsyncDemo("jiangnii");
- // Execute begin method
- IAsyncResult ar = demo.BeginRun(null, null);
- // You can do other things here
- // Use AsyncWaitHandle.WaitOne method to block thread for 1 second at most
- ar.AsyncWaitHandle.WaitOne(1000, false);
- if (ar.IsCompleted)
- {
- // Still need use end method to get result,
- // but this time it will return immediately
- string demoName = demo.EndRun(ar);
- Console.WriteLine(demoName);
- }
- else
- {
- Console.WriteLine("Sorry,
- can't get demoName, the time is over");
- }
- }
- }
C#異步編程模式IAsyncResult要注意的還有:不中斷的循環(huán),每次循環(huán)輸出一個(gè) "."
- class AsyncTest
- {
- static void Main(string[] args)
- {
- AsyncDemo demo = new AsyncDemo("jiangnii");
- // Execute begin method
- IAsyncResult ar = demo.BeginRun(null, null);
- Console.Write("Waiting..");
- while (!ar.IsCompleted)
- {
- Console.Write(".");
- // You can do other things here
- }
- Console.WriteLine();
- // Still need use end method to get result,
- //but this time it will return immediately
- string demoName = demo.EndRun(ar);
- Console.WriteLine(demoName);
- }
- }
***是使用回調(diào)方法并加上狀態(tài)對(duì)象,狀態(tài)對(duì)象被作為 IAsyncResult 參數(shù)的 AsyncState 屬性被傳給回調(diào)方法?;卣{(diào)方法執(zhí)行前不能讓主線程退出,我這里只是簡單的讓其休眠了1秒。另一個(gè)與之前不同的地方是 AsyncDemo 對(duì)象被定義成了類的靜態(tài)字段,以便回調(diào)方法使用
- class AsyncTest
- {
- static AsyncDemo demo = new AsyncDemo("jiangnii");
- static void Main(string[] args)
- {
- // State object
- bool state = false;
- // Execute begin method
- IAsyncResult ar = demo.BeginRun(
- new AsyncCallback(outPut), state);
- // You can do other thins here
- // Wait until callback finished
- System.Threading.Thread.Sleep(1000);
- }
- // Callback method
- static void outPut(IAsyncResult ar)
- {
- bool state = (bool)ar.AsyncState;
- string demoName = demo.EndRun(ar);
- if (state)
- {
- Console.WriteLine(demoName);
- }
- else
- {
- Console.WriteLine(demoName + ", isn't it?");
- }
- }
- }
C#異步編程模式IAsyncResult的后話:
對(duì)于一個(gè)已經(jīng)實(shí)現(xiàn)了 BeginOperationName 和 EndOperationName方法的對(duì)象,我們可以直接用上述方式調(diào)用,但對(duì)于只有同步方法的對(duì)象,我們要對(duì)其進(jìn)行異步調(diào)用也不需要增加對(duì)應(yīng)的異步方法,而只需定義一個(gè)委托并使用其 BeginInvoke 和 EndInvoke 方法就可以了。
C#異步編程模式IAsyncResult的基本情況就向你介紹到這里,希望對(duì)你了解和學(xué)習(xí)C#異步編程模式IAsyncResult有所幫助。
【編輯推薦】