我有一对一关系的WCF客户端和服务(即每个客户端一个服务主机)。我使用回调契约将消息从服务传递到客户端。
[ServiceContract(CallbackContract = typeof(IMessageTarget)]
public interface IMessageService
{
[OperationContract]
void StartMessages();
}
public interface IMessageTarget
{
[OperationContract]
Task SendAsync(Message message);
[OperationContract(IsOneWay = true)]
void Complete();
[OperationContract(IsOneWay = true)]
void Fault(ExceptionDetail exception);
}
在客户端上,我设置了双工连接以开始通信。调用MessageTarget.Completion
或Complete()
方法时Fault(ExceptionDetail)
完成。
IMessageTarget target = new MessageTarget();
var channelFactory = new DuplexChannelFactory<IMessageService>(target, new NetNamedPipeBinding());
IMessageService service = channelFactory.CreateChannel(new EndpointAddress(EndpointUri));
service.StartMessages();
await target.Completion;
服务一旦可用,就会向客户端发送消息。客户端可以通过让SendAsync()
花费很长时间返回来延迟更多消息。
IMessageTarget client = OperationContext.Current.GetCallbackChannel<IMessageTarget>();
// later, whenever a message is created
await client.SendAsync(message);
// finally
client.Complete();
我发现如果服务崩溃,客户端会挂起。不幸的是,除了调用服务方法并捕获CommunicationException
之外,WCF没有提供检测服务是否仍然运行的可靠方法。因此,我添加了一个新的操作
[OperationContract]
Task PingAsync();
因此客户端可以监控服务是否停止。
service.StartMessages();
while (!target.Completion.IsCompleted)
{
await service.PingAsync();
await Task.Delay(TimeSpan.FromSeconds(0.5));
}
await target.Completion;
这不会破坏使用回调的目的吗?我一直在努力想看看这个&#34;在不断砰砰的同时聆听回调&#34;策略优于简单地轮询最新消息(不需要双工)。我是否过度设计了这个,或者回调还有其他好处吗?
答案 0 :(得分:1)
大多数与WCF相关的异常都来自CommunicationsException,所以你在这个意义上做得很好。正如您所指出的,ping / polling违背了回调实现的目的。最重要的是,您需要调用服务并准备好处理服务调用期间发生的任何异常。没有可靠的方法来确定该服务是否可用。
如果您还没有这样做,您还可以查看IClientChannel事件,以监控连接发生的情况。
client.InnerChannel.Closed += OnChannelClosed;
client.InnerChannel.Opening += OnChannelOpening;
client.InnerChannel.Opened += OnChannelOpened;
client.InnerChannel.Closing += OnChannelClosing;
client.InnerChannel.Faulted += OnChannelFaulted;
client.InnerChannel.UnknownMessageReceived += OnChannelUnknownMessageReceived;