本章內容
請求/響應
請求/響應通信是指客戶端向服務端發送消息後,服務端會向客戶端發送響應。這也意味著在接收到服務的響應以前,客戶端不會繼續執行操作。
[OperationContract] string getOrders(DateTime dt);
請求/響應模式是默認的消息模式。
返回值是void,也屬於請求/響應消息交換。
除非客戶端異步調用操作,否則客戶端將停止處理,直到收到返回消息,即使該消息正常情況下為空時也是如此。
缺點
– 如果執行操作需要很長的時間,則會降低客戶端性能和響應能力。
優點
– 響應消息中可返回SOAP 錯誤,這表明可能在通信或處理中發生了一些與服務有關的錯誤狀況。
單向通信應是指通信只在一個方向進行,即從客戶端流向服務。服務不會發送響應,而客戶端也不會期望會有響應。這種情況下,客戶端發送消息,然後繼續執行。
單向操作是客戶端調用操作並在WCF 將消息寫入網絡後繼續進行處理的操作。通常這意味著,除非在出站消息中發送的數據極其龐大,否則客戶端幾乎立即繼續運行(除非發送數據時出錯)。此種類型的消息交換模式支持從客戶端到服務應用程序的類似於事件的行為。
若要為返回void 的操作指定單向消息交換,請將IsOneWay 屬性設置為true,默認為false.
[OperationContract(IsOneWay=true)] void insertEmp(Employee emp);
雙工模式的特點是,無論使用單向消息發送還是請求/答復消息發送方式,服務和客戶端均能夠獨立地向對方發送消息。對於必須直接與客戶端通信或向消息交換的任意一方提供異步體驗(包括類似於事件的行為)的服務來說,這種雙向通信形式非常有用。
– 若要設計雙工協定,還必須設計回調協定,並將該回調協定的類型分配給標記服務協定的ServiceContractAttribute 屬性(attribute)的CallbackContract 屬性(property)。
– 若要實現雙工模式,您必須創建第二個接口,該接口包含在客戶端調用的方法聲明
[ServiceContract(SessionMode=SessionMode.Required, CallbackContract=typeof(IServiceDuplexCallback))] public interface IServiceClass { [OperationContract(IsOneWay = true)] void AddNumber(); } public interface IServiceDuplexCallback { [OperationContract(IsOneWay = true)] void Calculate(double result); }
WCF異步的二種方式
用svcutil生成異步功能的代理類
修改接口定義異步方法
異步與線程
異步操作的優缺點
異步調用(asynchronous call)
操作系統發展到今天已經十分精巧,線程就是其中一個傑作。操作系統把 CPU 處理時間劃分成許多短暫時間片,在時間 T1 執行一個線程的指令,到時間 T2又執行下一線程的指令,各線程輪流執行,結果好象是所有線程在並肩前進。這樣,編程時可以創建多個線程,在同一期間執行,各線程可以“並行”完成不同的任務。
在單線程方式下,計算機是一台嚴格意義上的馮·諾依曼式機器,一段代碼調用另一段代碼時,只能采用同步調用,必須等待這段代碼執行完返回結果後,調用方才能繼續往下執行。
有了多線程的支持,可以采用異步調用,調用方和被調方可以屬於兩個不同的線程,調用方啟動被調方線程後,不等對方返回結果就繼續執行後續代碼。
比如:比如FileStream對象的Read方法
同步方式
int Read(byte[] buffer,int offset,int count)
異步方式
IAsyState BeginRead(byte[] buffer,int offset,int count, IAsyncResult callback,Object asyState)
int EndRead(IAsyncResult ar)
WCF異步的二種方式
異步與否由客戶端來決定,在設計之初,不應該去考慮服務的調用者調用的方式。
WCF可以由二種方式生成客戶端異步調用的代理類:
1、用svcutil生成異步功能的代理類
2、修改接口定義異步方法
我們用svcutil來生成客戶端代理代碼的時候,只需添加 /async便可以生成有異步功能的代理類了.
而在IDE中,操作就更加簡單,就是在添加ServiceReference的時候,選擇高級選項,鉤選“創建異步方法”
示例:
//異步 private void button1_Click(object sender, EventArgs e) { myService.Service1Client client = new client.myService.Service1Client(); client.helloCompleted += new EventHandler<client.myService.helloCompletedEventArgs>(client_helloCompleted); client.helloAsync("my god"); //client.Beginhello("my god", doCallBack, client); } void client_helloCompleted(object sender, client.myService.helloCompletedEventArgs e) { MessageBox.Show(e.Result); } //private void doCallBack(IAsyncResult ar) //{ // string s = ((myService.Service1Client)ar.AsyncState).Endhello(ar); // MessageBox.Show(s); //}
異步調用方法2
修改在客戶端的服務定義,增加操作的異步方法。
在客戶端決定采用異步方式調用服務的操作時,雖然需要修改客戶端的服務契約接口,但並不會影響服務端的契約定義。
[OperationContract(AsyncPattern = true, Action = "",ReplyAction="")] IAsyncResult BeginTransferFile(AsyncCallback callback, object asyncState); byte[] EndTransferFile(IAsyncResult result);