WCF服务回调调用上的奇怪死锁

时间:2015-01-16 10:49:11

标签: .net wcf deadlock wcf-callbacks

我在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语句之前处理回调,而日志却反过来呢?

0 个答案:

没有答案