2013-03-27 55 views
0

我有一个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); 
    } 

当有什么东西上报业务正在执行一些工作和报告。 参数类别被标记为DataContract与名称空间。它们包含.Net本机类型(int,stringDateTime)。

我创建了一个测试应用程序,一切都很好(从询问服务执行到ExecutionStarted被称为〜1秒的时间)。

当创建在我现有的应用程序客户端,有2个问题:

  1. 步履维艰 - 约1分钟从Execute()ExecutionStarted()
  2. 最后一次电话 - ExecutionEnded - 只是不会发生。会发生什么?最后的OutputAvailable呼叫发生。在调试过程中,我看到服务调用ExecutionEnded方法,但在客户端调用的是OutputAvailable(应该只调用它,而不是调用finish方法)。

我在我的测试客户端和我的真实应用程序中使用相同的测试。

一些代码,也许会有帮助,我希望:

服务

类声明:

[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 

之前的“执行”方法返回,后来我得到:

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问题,您应该添加在你的回调实现如下:(感谢Ian Ringrose提供答案here

[CallbackBehavior(UseSynchronizationContext = false)] 


现在我仍面临一个不响应的WPF客户端,但与服务的连接不挂起。我会很感激更多的建议。

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

回答

0

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

  1. 在服务溶液,重命名问题方法(在ICallback接口)。
  2. 重新编译并更新并重新编译有问题的应用程序。
  3. 运行该应用程序,该方法突然被调用。
  4. 将该方法重命名为原始名称。
  5. 赢!
0

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

+0

我不确定你是什么意思的异步方法。我正在使用服务界面中公开的方法。 另外,不知道你的意思是静态服务(我是'WCF')。 请参阅我的编辑。 – Noich 2013-03-28 08:38:53

+0

soory我不清楚,我的意思是你的服务链接是静态的,可以解决你最后的问题,就像异步部分一样,使用它来访问你的web服务。我发现了一个链接,其中描述了asynccallback [link] http://stackoverflow.com/questions/1047662/what-is-asynccallback – machie27 2013-03-28 14:43:40

相关问题