我在WCF服务上遇到死锁问题,我无法理解为什么因为每个调用都在同一个锁上同步。 这是我的客户/服务配置。
结合=" NetTcpBinding的"
服务配置:ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession,ConcurrencyMode = ConcurrencyMode.Reentrant,UseSynchronizationContext = false)
回调配置:CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant,UseSynchronizationContext = false)
代码(我简化了类和方法名称以便澄清):
interface ICallBack{
void OnDoAction(string info);
}
interface IMyService{
Report DoAction( string param);
}
public class MyClient:ICallBack{
void OnDoAction(string info){
Task.Factory.StartNew(() => {Console.WriteLine("Received info=["+info+"]"); });
}
Main(){
MyClient client = new MyClient();
InstanceContext context = new InstanceContext(client);
DuplexChannelFactory<IMyService> duplexChannelFactory = new DuplexChannelFactory<IMyService>(context, "MyService");
IMyService service = duplexChannelFactory.CreateChannel();
Report report = service.DoAction("Param1");
}
}
public class MyService:IMyService{
ICallback callback;
public MyService(){
callback = OperationContext.Current.GetCallbackChannel<ICallBack>();
}
public Report DoAction(){
lock(callback){
try{
Report r = null;
try{
Log("Do action");
r = executeAction();
}catch(Exception e){
r = new Report("Error in DoAction");
}
Log("Do action done");
return report;
}finally{
Log("Do action has returned");
}
}
}
public void CallbackAfterDoAction(string info){
lock(callback){
callback.OnDoAction(info);
}
}
}
以异步方式在单独的线程中调用回调。
当我从客户端调用DoAction()
方法时,会出现死锁并且我有一个TimeoutException:
2015-01-16 10:42:17,463 [8]错误 - (OrderManagerViewModel.cs:311) - CancelOrder:System.TimeoutException:Cette op곡de de dedede envoyꥠet.tcp:// localhost:8002 / NetsOrderManagerServiceRemote / n&#39; a pas 重新发布(00:00:05)。 Le temps allou顠cette 选择公平的事情 - 联合国d&#39;undꭡd&#39;注意加长。 Ceci peut뵲e d fait que le service est toujours en cours de traitement de 我可以通过消息传递消息来解决问题。 Envisagez d&#39; augmenterledꭡid&#39; attente de l&#39; op(en diffusant le canal / proxy)
IContextChannel etendꧩnissantlapropri굩OperationTimeout)et v곩fiez que le service peut se connecter au client。服务器堆栈跟踪:
ࡓystem.ServiceModel.Dispatcher.DuplexChannelBinder.SyncDuplexRequest.WaitForReply(时间跨度 超时)
ࡓystem.ServiceModel.Dispatcher.DuplexChannelBinder.Request(消息 消息,TimeSpan超时)
ࡓystem.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway,ProxyOperationRuntime操作,Object [] ins, 对象[]出局,TimeSpan超时)
ࡓystem.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway,ProxyOperationRuntime操作,Object [] ins, 对象[]出局)
ࡓystem.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall,ProxyOperationRuntime operation)
ࡓystem.ServiceModel.Channels.ServiceChannelProxy.Invoke(即时聊天 消息)在[0]处重新抛出异常:
ࡓystem.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(即时聊天 reqMsg,IMessage retMsg)
ࡓystem.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&安培; msgData,Int32类型)
ࡎets.Core.API.OrderManager.Service.IOrderManager.CancelOrder(ICancelOrderRequest cancelRequest)
ࡎets.Core.Client.Wcf.OrderServiceWcfClient.RemoteOrderManagerServiceProxy.CancelOrder(ICancelOrderRequest 取消请求)dans C:\ dev的\ GitProjects \ NetsCoreLibProject \ NetsCoreLib \ Nets.Core.Client.Wcf.OrderServiceWcfClient \ RemoteOrderManagerServiceProxy.cs:LIGNE 340个
ࡎets.Core.Prototype.Client.ViewModels.OrderManagerViewModels.OrderManagerViewModel.CancelOrder(对象 参数)dans C:\ dev的\ GitProjects \ NetsCoreLibProject \ NetsCoreLib \ Nets.Core.Prototype.Client \的ViewModels \ OrderManagerViewModels \ OrderManagerViewModel.cs:LIGNE 302
下面的服务器日志显示DoAction()
在回执执行之前返回。
执行操作记录日志:
2015-01-16 11:13:57,342 [27]信息 - (RemoteOrderManagerService.cs:195) - CancelOrder:RemoteOrderService :服务器调用的CancelOrder操作2015-01-16 11:13:57,342 [27] INFO - (RemoteOrderManagerService.cs:203) - CancelOrder: RemoteOrderService:CancelOrder操作返回报告= [CancelOrder 报告netsd2dce |无法验证过滤器订单一致性检查 2015-01-16 11:13:57,342 [27]信息 - (RemoteOrderManagerService.cs:208) - CancelOrder:RemoteOrderService :CancelOrder操作返回完成
CallbackAfterDoAction调用日志:
2015-01-16 11:13:57,342 [EventQueue-ThreadDispatcher-HighPriorityEventQueue-2] INFO - (OrderManagerService.cs:451) - DispatchErrorOnOrder:Dispatch错误 在订购NetsOrderId [netsd2dce] 2015-01-16 11:13:57,342 [EventQueue-ThreadDispatcher-HighPriorityEventQueue-2] INFO - (Order.cs:760) - OnCancelAck:OnCancelAck [[Order#ob_,ba3(netsd2dce)) 买1 [TOTF.PA] @ 47] |所有者= []]:无法执行请求= [取消]原因 订单= [[订单#ob_,ba3(netsd2dce)买1 [TOTF.PA] @ 47] |所有者= []]是 在最终状态= [取消] 2015-01-16 11:13:57,343 [EventQueue-ThreadDispatcher-HighPriorityEventQueue-2] INFO - (Order.cs:765) - OnCancelAck:OnCancelAck [[Order#ob_,ba3(netsd2dce)) 买1 [TOTF.PA] @ 47] |所有者= []]:来电 Nets.Core.Service.Remote.RemoteOrderManagerService
但是:当我在服务上评论回调调用时,DoAction()方法正确执行。 它就好像在发生死锁时DoAction方法返回之前调用了回调一样。 我不明白发生了什么,因为每个被调用的方法都在同一个锁上同步。
PS:如果我在回调之前添加一个睡眠:
public void CallbackAfterDoAction(){
lock(callback){
Thread.Sleep(3);
callback.OnDoAction();
}
}
死锁永远不会发生,直到睡眠(3),但是值<&lt; 3 ms发生死锁。 ==&GT;所以问题是为什么在DoAction()方法的return语句之前处理回调,而日志却反过来呢?