WCF 雙向通訊允許 Service 主動回呼 Client。本範例沿用數學運算情境:Client 傳遞運算元與一個回呼物件,Server 運算完成後透過 Callback 將結果回傳 Client 顯示。專案結構包含五個專案:Contract、Service、Hosting (Self-host)、Client、IIS Host 網站。
在 Contract 專案中定義兩個介面:
[ServiceContract(CallbackContract = typeof(ICalculatorCallback))]
public interface IDuplexCalculator
{
[OperationContract]
void Add(double x, double y);
}
[ServiceContract]
public interface ICalculatorCallback
{
[OperationContract]
void ShowResult(double x, double y, double result);
}
關鍵點:
CallbackContract 參數指定回呼介面,使 Service 知道如何回呼 Client。[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class DuplexCalculatorService : IDuplexCalculator
{
public void Add(double x, double y)
{
double result = x + y;
ICalculatorCallback callback = OperationContext.Current.GetCallbackChannel<ICalculatorCallback>();
callback.ShowResult(x, y, result);
}
}
注意事項:
ConcurrencyMode.Multiple 或 Reentrant,避免死鎖。預設 Single 模式下,InstanceContext 被鎖定,Service 發起外呼叫時無法重入。OperationContext.Current.GetCallbackChannel<T>() 取得 Client 端的 Callback 通道。App.config 關鍵設定:
<services>
<service name="Artech.WCFService.Service.DuplexCalculatorService" behaviorConfiguration="calculatorServieBehavior">
<endpoint binding="wsDualHttpBinding" contract="Artech.WCFService.Contract.IDuplexCalculator" />
<host>
<baseAddresses>
<add baseAddress="https://localhost:7777/DuplexCalculator" />
</baseAddresses>
</host>
</service>
</services>
Program.cs 啟動 Host:
using (ServiceHost host = new ServiceHost(typeof(DuplexCalculatorService)))
{
host.Opened += delegate { Console.WriteLine("Duplex calculator Service has begun to listen"); };
host.Open();
Console.Read();
}
Client 需實作 Callback 介面並建立雙向 Proxy:
public class CalculatorCallbackHandler : ICalculatorCallback
{
public void ShowResult(double x, double y, double result)
{
Console.WriteLine("x + y = {2} where x = {0} and y = {1}", x, y, result);
}
}
public class DuplexCalculatorClient : ClientBase<IDuplexCalculator>, IDuplexCalculator
{
public DuplexCalculatorClient(InstanceContext callbackInstance) : base(callbackInstance) { }
public void Add(double x, double y) { this.Channel.Add(x, y); }
}
Client 端 App.config 需設定 clientBaseAddress 讓 Service 能回呼:
<wsDualHttpBinding>
<binding name="wsDualBinding_IDuplexCalculator" clientBaseAddress="https://localhost:6666/myClient/" />
</wsDualHttpBinding>
Program.cs 呼叫:
CalculatorCallbackHandler handler = new CalculatorCallbackHandler();
using (DuplexCalculatorClient client = new DuplexCalculatorClient(new InstanceContext(handler)))
{
Console.WriteLine("Begin to invocate duplex calculator");
client.Add(1, 2);
}
建立 .svc 檔並複製 Host 端的 system.serviceModel 設定至 Web.config,修改 Client 端 endpoint address 指向 .svc 網址即可在 IIS 中執行相同功能。