應用框架的設計與實現——.NET平臺(7.事件通知服務.委託.異步編程)

7.2.1 委託
取得消息接收者列表  delesobj.GetInvocationList()
調用每個委託目標  deleobj.DynamicInvoke()

Delegate[] delegates = allTargets.GetInvocationList();
object[] params = {4,3};
foreach (Delegate dg in delegates)
{
    
try
    
{
        
int result = (int)dg.DynamicInvoke(params);
        Console.WriteLine(
"result is {0}", result);
    }

    
catch (Exception ex)
    
{
        
// ignore the exception
    }

}


7.2.2 異步編程
異步調用委託  dele.BeginInvoke(p1, p2, p3, p4) // 後兩個參數是回調方法相關的,前面是委託方法的參數
委託方法結果的信息  IAsynResult
委託是否執行結束  IAsynResult.IsCompleted
獲取委託方法的結果  dele.EndInvoke(IAsynResult)


委託對象有個方法 BeginInvoke() 可以使委託對象以異步方式(新線程內)運行,該方法是編譯時編譯器爲委託對象加入的。
委託對象運行在內部線程池中,內部線程池是什麼?
每個應用程序域有一個線程池,默認包含25個線程。當通過 BeginInvoke() 調用委託時,CLR將使用這個線程池處理委託。
如果異步委託太多,超過了線程池中的空閒線程數,CLR會自動讓委託排隊,當有線程閒置時再處理它們。

CalculationHandler slowAddHandler = new CalculationHandler(math.SlowAdd);
// 異步方式調用方法
IAsynResult ar = slowAddHandler.BeginInvoke(43nullnull);
// 檢查方法是否已經執行完
while (!ar.IsCompleted)
{
    System.Threading.Thread.Sleep(
1000);
}

// 取得方法執行結果
object slowResult = slowAddHandler.EndInvoke(ar);
Console.Write(
"SlowAdd returns " + (int)slowResult);


如何使用異步調用方法的回調方法?如何使用 BeginInvoke() 方法的後兩個參數?
1.BeginInvoke() 方法的倒數第二個參數是委託對象 AsyncCallback() 類型,
1.1當異步委託方法執行完後異步委託會執行回調函數,這樣我們“不停的檢查異步委託方法是否執行完”的問題也解決了。
1.2委託對象 AsyncCallback() 有一個參數是 IAsynResult 類型的,
1.3當異步委託執行回調函數時會以 BeginInvoke() 返回的 IAsynResult 對象爲參數的,
2.同時 BeginInvoke() 的倒數第一個參數會以 IAsynResult.AsyncState 屬性的形式出現。

AsyncCallback 委託的定義如下(類庫內定義的):
public delegate void AsyncCallback(IAsyncResult asyncResult)


回調方法:
resultObject.AsyncDelegate  取得異步委託
result.AsyncState  BeginInvoke()的最後一個參數

public void OnSlowAddComplete(IAsyncResult result)
{
    AsyncResult resultObject 
= (AsyncResult)result;
    
// 取得委託對象
    CalculationHandler completedDelegate = (CalculationHandler)resultObject.AsyncDelegate;
    
// 取得返回值
    int sum = (int)completedDelegate.EndInvoke(result);
    Console.WriteLine(
"the result is " + sum);
    Console.WriteLine(
"the last parameter is " + result.AsyncState.ToString());
}


執行異步委託方法時使用回調方法:
AsyncCallback callback = new AsyncCallback(this.OnSlowAddComplete);
IAsynResult ar 
= slowAddHandler.BeginInvoke(43, callback, "last 參數");



當應用的流程需要多個方法都有結果才能繼續時,我們必須等每個方法都執行結束。
如何等每個方法都執行結束?
WaitHandle[]  異步委託等待句柄數組
ar1.AsyncWaitHandle
WaitHandle.WaitAll()  阻塞當前線程,直到所有異步委託方法執行完

IAsynResult ar1 = slowAdd.BeginInvoke(52nullnull);
IAsynResult ar2 
= sub.BeginInvoke(33nullnull);
IAsynResult ar3 
= multiply.BeginInvoke(413nullnull);
WaitHandle[] waitArray 
= {ar1.AsyncWaitHandle, ar2.AsyncWaitHandle, ar3.AsyncWaitHandle};
WaitHandle.WaitAll(waitArray);
int result1 = slowAdd.EndInvoke(ar1);
int result2 = sub.EndInvoke(ar2);
int result3 = multiply.EndInvoke(ar3);
Console.Write(result1 
+ result2 + result3);


異常:
我們不知道異步委託什麼時候發生異常,也不能即時處理它。
如果有異常發生了,我們怎麼捕獲它哪?
如果有異常會在調用 EndInvoke() 方法時拋出

IAsynResult ar1 = slowAdd.BeginInvoke(52nullnull);
WaitHandle.WaitAll(
new WaitHandle[]{ar1});
try
{
    
int result1 = slowAdd.EndInvoke(ar1);
}

catch (Exception ex)
{
    Console.Write(ex.Message);
}
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章