对于双工通讯来说,服务对客户端的回调也是通过代理完成的。那么这又涉及到另外一个问题:回调客户端时,能否让回调服务也并发执行呢?WCF中定义了CallbackBehaviorAttribute ,可以通过它来设置回调服务的行为。它同样定义了ConcurrencyMode,可指定回调的并发模式,但它没有定义回调的实例模式,即InstanceContextMode。本文主要探讨服务的并发与回调服务的并发。
目录:
- 测试重入与回调并发
- 会话对 重入与回调并发
- 设置服务并发的ServiceBehaviorAttribute能用于回调服务吗?
publicinterface IAdd
{ [OperationContract] void Add(int x, int y);}{
[OperationContract] void ShowResult(int result); }{
private readonly int counter; public AddService() { counter++; Console.ResetColor(); Console.WriteLine(string.Format("AddService Construction function excute... counter is {0}", counter)); } #region IAdd 成员 public void Add(int x, int y) { var clientId = OperationContext.Current.IncomingMessageHeaders.GetHeader<int>(MessageWrapper.headerClientId, MessageWrapper.headerNamespace); Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(string.Format("Time:{0};ThreadId is :{1}.Request Id is {2} Add Method Invoked,", DateTime.Now, Thread.CurrentThread.ManagedThreadId, clientId)); Thread.Sleep(5000); int result = x + y; MessageHeader<int> header = new MessageHeader<int>(clientId); System.ServiceModel.Channels.MessageHeader messageHeader = header.GetUntypedHeader(MessageWrapper.headerClientId, MessageWrapper.headerNamespace); OperationContext.Current.OutgoingMessageHeaders.Add(messageHeader); Console.WriteLine(string.Format("Time: {1} Requst Id {0} begin Callback",clientId,DateTime.Now)); IAddCallback callbackProxy= OperationContext.Current.GetCallbackChannel<IAddCallback>(); callbackProxy.ShowResult(result); Console.WriteLine(string.Format("Time: {1} Requst Id {0} Callback finished", clientId, DateTime.Now)); Console.WriteLine(string.Format("result is : {0}",result)); Thread.Sleep(5000); Console.WriteLine("=========Excute finished========="); Console.WriteLine(); } #endregion }<services>
<service name="Service.AddService"> <endpoint address="http://127.0.0.1:3636/AddService" binding="wsDualHttpBinding" contract="Contract.IAdd" ></endpoint> </service> </services> </system.serviceModel>
服务端:ConcurrencyMode = ConcurrencyMode.Reentrant,InstanceContextMode = InstanceContextMode.Single
测试2:
服务端:ConcurrencyMode = ConcurrencyMode.Reentrant,InstanceContextMode = InstanceContextMode.Single
服务端:ConcurrencyMode = ConcurrencyMode.Reentrant,InstanceContextMode = InstanceContextMode.PerSession
服务端:ConcurrencyMode = ConcurrencyMode.Reentrant,InstanceContextMode = InstanceContextMode.PerCall
服务端输出:
服务端:ConcurrencyMode = ConcurrencyMode.Reentrant,InstanceContextMode = InstanceContextMode.Single
服务端:ConcurrencyMode = ConcurrencyMode.Reentrant,InstanceContextMode = InstanceContextMode.PerSession
客户端输出:
服务端:ConcurrencyMode = ConcurrencyMode.Reentrant,InstanceContextMode = InstanceContextMode.PerSession
客户端输出:
服务端:ConcurrencyMode = ConcurrencyMode.Reentrant,InstanceContextMode = InstanceContextMode.PerSession
服务端:ConcurrencyMode = ConcurrencyMode.Reentrant,InstanceContextMode = InstanceContextMode.PerSession
服务端:ConcurrencyMode = ConcurrencyMode.Reentrant,InstanceContextMode = InstanceContextMode.PerSession
服务端:ConcurrencyMode = ConcurrencyMode.Reentrant,InstanceContextMode = InstanceContextMode.PerSession
服务端:ConcurrencyMode = ConcurrencyMode.Reentrant,InstanceContextMode = InstanceContextMode.PerSession
服务端:ConcurrencyMode = ConcurrencyMode.Reentrant,InstanceContextMode = InstanceContextMode.PerSession
客户端:ConcurrencyMode = ConcurrencyMode.Single
ConcurrencyMode = ConcurrencyMode.Reentrant,InstanceContextMode = InstanceContextMode.PerSession
ConcurrencyMode = ConcurrencyMode.Reentrant,InstanceContextMode = InstanceContextMode.PerSession
客户端输出:
ConcurrencyMode = ConcurrencyMode.Reentrant,InstanceContextMode = InstanceContextMode.PerCall
客户端输出:
ConcurrencyMode = ConcurrencyMode.Reentrant,InstanceContextMode = InstanceContextMode.Single
服务端输出:
客户端输出:
服务端:ConcurrencyMode = ConcurrencyMode.Reentrant,InstanceContextMode = InstanceContextMode.PerCall
客户端:ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple,InstanceContextMode = InstanceContextMode.PerCall)
服务端输出:
客户端输出:
由测试10、11、12、18这些测试得出如下结论:ServiceBehaviorAttribute对回调服务的并发设置无效。
会话模式下,不同客户端代理对可重入的服务总是以并发的方式执行;相同客户端对可重入的服务总是以串行的方式执行,而无论怎样,回调服务总是以串行的方式执行。