熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

wcf多線程和異步操作

2013-11-13 10:14:54  來源: .NET編程 

  按照操作執行所需的資源類型我們可以將操作分為cpu綁定型操作和I/O綁定型操作前者主要是利用cpu進行密集運算後者大部分操作處理時間花在I/O處理上(比如文件系統網絡資源)對於I/O綁定型的操作我們可以充分利用多線程機制讓多個操作在各自的線程上並行執行
   
    服務調用就是典型的I/O綁定型操作所以多線程在服務調用具有廣泛應用按照異步操作發生的位置可以將wcf應用的異步操作分為下面中類型
   
    異步信道調用客戶端通過綁定創建的信道向服務端發送消息從而實現了對服務的調用客戶端可以通過代理對象異步的調用信道從而實現異步服務的調用
   
    單向消息交換客戶端的信道通過單向的消息交換模式向服務端發送消息消息一旦抵達傳輸層馬上返回從而達到異步服務調用的效果
   
    異步服務實現服務端在具體實現服務操作的時候采用異步調用的方式
   
異步服務的調用
   
    異步服務代理的創建
   
    一般的服務代理繼承自ClientBase<TChannel>默認情況下是不具有異步服務調用的操作但我們可以通過添加引用的方式創建異步服務代理並對服務進行異步調用
   
    在添加服務引用的時候在彈出的服務引用對話框中點擊高級按鈕會彈出服務引用設置對話框然後勾選生成異步操作即可

   
    
    對應生成的服務代理類中就會多出幾個方法(下面都以計算的服務為例)以下幾個方法在接下來都會介紹到的
   
    [csharp]
   
    public partial class CalculatorClient:ClientBase<ICalculator>ICalculator
   
    {
   
    public event SystemEventHandler<AddCompleteArgs> AddComplete;
   
    public IAsyncResult BeginAdd(double xdouble yAsyncCallback callbackobject asuncState)
   
    public double EndAdd(SystemIAsyncReuslt result)
   
    public AddAsync(double xdouble y)
   
    public AddAsync(double xdouble yobject userState)
   
    }
   
    其中Add用於同步服務調用BeginAdd/EndAdd則用於異步調用注意應用在BeginAdd方法上的OperationContractAttributes特性的AsyncPattern屬性被設置成True
   
    通過BeginXxx/EndXxx進行異步服務調用
   
    調用BeginXxx方法讓相應的操作在另一個線程執行方法會立即返回一個IAsyncResult類型的對象此時我們可以在當前線程執行額外的操作異步操作執行的結果通過調用EndXxx方法得到而該方法的參數為調用BeginXxx方法得到的IAsyncResult對象通過添加計算服務引用生成的代理類型CalculatorClient為例
   
    [csharp]
   
    CalculatorClient proxy=new CalculatorClient()
   
    IAsyncResult asyncResult=proxyBeginAdd(nullnull)
   
    //其他操作
   
    //Endxx方法可以根據異步操作可能的執行時間來決定調用執行一旦Endxxx方法被調用後當前線程會被阻塞直到異步操作之行結束
   
    double result=proxyEndAdd(asyncResult)
   
    proxyClose()
   
    ConsoleWriteLine(x+y={} when x={} and y={}result)
   
    注意一個極端的例子是在調用BeginXxx方法後就直接調用EndXxx方法雖然在不同的線程中 但基本沒有起到異步的作用這裡可以用回調的方式來解決這個問題


   
    通過回調的方式進行異步服務調用
   
    我們可以看看上面服務代理類中多出來的幾個方法中BeginAdd方法
   
    public IAsyncResult BeginAdd(double xdouble yAsyncCallback callbackobject asyncState)
   
    ①其中參數類型為AsyncCallback的callbackAsyncCallback是個參數類型為IAsyncResult無返回值的委托
   
    ②參數asyncState可以用於向回調操作傳遞一些額外的參數在BeginAdd方法中指定的asyncState可以通過IAsyncResult的AsyncState屬性獲得
   
    [csharp]
   
    public delegate void AsyncCallback(IAsyncResult ar)
   
    public interface IAsyncResult
   
    {
   
    object AsyncState {get;}
   
    WaitHandle AsyncWaitHandle {get;}
   
    bool CompletedSynchronously { get;}
   
    bool IsCompleted { get;}
   
    }
   
    下面通過一個匿名方法的形式定義回調操作由於在回調操作中輸出運算結果時需要用到參與的運算數我們通過BeginAdd方法的asyncState參數實現向回調操作傳遞數據
   
    在回調操作中通過IAsyncResult對象的AsyncState獲得操作數
   
    [csharp]
   
    CalculatorClient proxy=new CalculatorClient()
   
    proxyBeginAdd(
   
    delegate(IAsyncResult asyncResult)
   
    {
   
    double[] operNums=asyncResultAsyncState as double[];
   
    double result=proxyEndAdd(asyncResult)
   
    proxyClose()
   
    ConsoleWriteLine(x+y={} when x={} and y={}operNums[]operNums[]result)
   
    }new double[] {})
   
    通過事件注冊的方式進行異步服務調用
   
    在那個異步服務代理類中還有兩個異步執行的AddAsync方法重載和一個AddComplete事件
   
    public AddAsync(double xdouble y)
   
    public AddAsync(double xdouble yobject userState)
   
    其中userState參數和BeginAdd方法的asyncState參數具有相同的作用
   
    [csharp]
   
    public event SystemEventHandler<AddCompleteEventArgs> AddComplete;
   
    public class AddCompleteEventArgs:EventArgs
   
    {
   
    public bool Cancelled{get;}
   
    public Exception Error{get;}
   
    public object UserState {get;}
   
    }
   
    事件參數AddCompleteEventArgs定義了個只讀屬性其中Cancelled表示異步操作是否取消異步操作拋出異常可以通過屬性Error得到UserState返回的是Addsync方法中的userState參數
   
    由於AddAsync方法是以異步方式執行的所以調用後會立即返回如果我們注冊了CalculatorClient的AddComplete事件他將在異步服務調用結束後被觸發所以我們可以按照如下方式調用服務代理Addsync方法
   
    [csharp]
   
    CalculatorClient proxy=new CalculatorClient()
   
    proxyAddComplete+=delegate(object sender AddCompleteEventArgs args)
   
    {
   
    double[] operNums=argsUserState as double[];
   
    double result=argsResult;
   
    proxyClose()
   
    ConsoleWriteLine(x+y={} when x={} and y={}operNums[]operNums[]result)
   
    };
   
    proxyAddAsync(new double[]{})


   
異步服務的實現
   
    上面介紹了如何調用異步服務但如何服務操作是如何以異步模式實現呢?
   
    異步操作模式
   
    前面提到過在OperationContractAttributes特性的AsyncPattern屬性如果將應用到某個操作的方法上設為True則意味著對應的操作需要采用異步模式來實現實際上客戶端生成的異步服務代理類實現的契約接口中也包含了這樣的異步操作
   
    異步服務操作是通過BeginXxx/EndXxx兩個配對的方法實現的只需將BeginXx方法的特性將屬性AsyncPattern設置為True即可
   
    三實例演示 下面通過異步模式來定義一個讀取文件的服務

  

  客戶端讀取


 


From:http://tw.wingwit.com/Article/program/net/201311/13034.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.