我有一个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
,string
,DateTime
)。
我创建了一个测试应用程序,一切都很好(从询问服务执行到ExecutionStarted
被称为〜1秒的时间)。
当创建在我现有的应用程序客户端,有2个问题:
- 步履维艰 - 约1分钟从
Execute()
到ExecutionStarted()
。 - 最后一次电话 -
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
现在它是唯一一个没有被称为客户端上的一个方法。这个连接还活着(我之后还有其他的调用),这个方法没有做任何特殊的事情。
我不确定你是什么意思的异步方法。我正在使用服务界面中公开的方法。 另外,不知道你的意思是静态服务(我是'WCF')。 请参阅我的编辑。 – Noich 2013-03-28 08:38:53
soory我不清楚,我的意思是你的服务链接是静态的,可以解决你最后的问题,就像异步部分一样,使用它来访问你的web服务。我发现了一个链接,其中描述了asynccallback [link] http://stackoverflow.com/questions/1047662/what-is-asynccallback – machie27 2013-03-28 14:43:40