两个客户端之间的不同服务行为

时间:2013-03-27 13:28:44

标签: c# wcf

我需要在现有应用程序中合并WCF服务 服务界面:

[ServiceContract(CallbackContract = typeof(IClientCallback))]
    public interface IExecutionService
    {
        [OperationContract]
        ExecutionStatus Execute(string path);

        [OperationContract]
        ExecutionStatus Abort();
    }

回调:

[ServiceContract]
    public interface IClientCallback
    {
        [OperationContract(IsOneWay = false)]
        string GetUserInput(string message, string information, bool isPause);

        [OperationContract(IsOneWay = true)]
        void OutputAvailable(OutputAvailableEventArgs args);

        [OperationContract(IsOneWay = true)]
        void ResultAvailable(ResultAvailableEventArgs args);

        [OperationContract(IsOneWay = true)]
        void ExecutionStarted(ExecutionStartedEventArgs args);

        [OperationContract(IsOneWay = true)]
        void ExecutionEnded(ExecutionEndedEventArgs args);
    }

该服务正在执行一些工作并报告何时需要报告。 Args类标记为DataContract,带有名称空间。它们包含.Net原生类型(intstringDateTime)。

我创建了一个测试应用程序,一切都运行良好(从询问服务执行到调用ExecutionStarted ~1秒的时间)。

在现有应用程序中创建客户端时,有两个问题:

  1. 缓慢 - 从Execute()ExecutionStarted()约1分钟。
  2. 最后一次通话 - ExecutionEnded - 只是没有发生。怎么了?最后OutputAvailable调用发生了。在调试期间,我看到服务调用ExecutionEnded方法,但在客户端调用的是OutputAvailable(应该已经调用,只是更早,而不是完成方法)。
  3. 我在我的测试客户端和我的实际应用程序中使用相同的测试。

    有些代码可能会有所帮助,我希望:

    服务

    类声明:

      [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Reentrant)]
            public class ExecutionService : IExecutionService
    
    public ExecutionStatus Execute(string path)
            {
                lock (locker)
                {
                    var tempClient = OperationContext.Current.GetCallbackChannel<IClientCallback>();
                    if (client == null)
                        client = tempClient;
                    else if (client != null && client != tempClient)
                    {
                        throw new FaultException(new FaultReason("Execution Service is busy processing a request."));
                    }
                    else if (tempClient == null)
                        throw new FaultException(new FaultReason("No client found, execution is aborted."));
                    Log.InfoFormat("client: "+ DateTime.Now);
                    Log.InfoFormat(client == null ? "null" : client.ToString());
                }
                ((IContextChannel)client).OperationTimeout = new TimeSpan(0,3,0);
                Task<ExecutionStatus> executionTask = Task.Factory.StartNew(() => HandleExecution(path));
                return executionTask.Result;
    }
    

    (确保我一次只有一个客户端。我需要重入模式,所以我可以在服务的方法中使用回调。)

    客户端: 创建与服务的连接:

     var myBinding = new WSDualHttpBinding();
     var myEndpoint = new EndpointAddress("http://localhost:3050/ExecutionService");
     var myChannelFactory = new DuplexChannelFactory<IExecutionService>(this, myBinding, myEndpoint);
     service = myChannelFactory.CreateChannel();
     var executionStatus = service.Execute(@"C:\Users\nosh\Desktop\launcher.py"); 
    

    如有必要,我会发布更多代码 另一个问题是,在我的真实应用程序中,我得到:

    A first chance exception of type 'System.TimeoutException' occurred in System.ServiceModel.dll
    A first chance exception of type 'System.TimeoutException' occurred in mscorlib.dll
    

    在'execute'方法返回之前,后来我得到:

    A first chance exception of type 'System.Runtime.Serialization.SerializationException' occurred in System.Runtime.Serialization.dll
    A first chance exception of type 'System.ServiceModel.Dispatcher.NetDispatcherFaultException' occurred in System.ServiceModel.dll
    A first chance exception of type 'System.ServiceModel.Dispatcher.NetDispatcherFaultException' occurred in System.ServiceModel.dll
    A first chance exception of type 'System.ServiceModel.Dispatcher.NetDispatcherFaultException' occurred in System.ServiceModel.dll
    A first chance exception of type 'System.ServiceModel.Dispatcher.NetDispatcherFaultException' occurred in System.ServiceModel.dll
    

    在我的测试应用程序中不会发生这种情况 知道这里有什么问题吗?

    修改
    我想我知道什么是错的,而不是如何解决它。问题是我的真实应用是WPF,并且在使用WCF时遇到了一些问题。我尝试切换到NetTcpBinding,但没有帮助。我很欣赏其他建议。

    编辑2
    对于WPF问题,您应该在回调实现中添加以下内容:

    [CallbackBehavior(UseSynchronizationContext = false)]
    

    (感谢Ian Ringrose提供答案here。)
    现在我仍然面临一个非响应WPF客户端,但与服务的连接不会挂起。我会感激更多的建议。

    编辑3
    现在它只是一个没有在客户端上调用的方法。连接是活的(我之后还有其他调用),该方法没有做任何特殊的事情。

2 个答案:

答案 0 :(得分:0)

我不知道您是如何设置服务的,但是您是否使用异步方法来调用服务?否则我建议你实现它。您的服务是静态的,因此也可能是问题,当您在其他设备上运行时,链接将无法正常工作。至于序列化错误我无法帮助。

答案 1 :(得分:0)

我想每个人都不时偶然发现这些WTF 我无法解释解决方案背后的逻辑,但解决方案本身很简单:

  1. 在服务解决方案中,重命名有问题的方法(在ICallback界面中)。
  2. 重新编译并更新并重新编译有问题的应用程序。
  3. 运行应用程序,突然调用该方法。
  4. 将该方法重命名为原始名称。
  5. 赢!