我有一个SOA应用程序,它使用Windows服务中托管的双工WCF服务.客户端本身是WPF应用程序.
我在关闭和重新启动客户端应用程序时看到异常行为.如果我在关闭一个实例后开始一个新实例,那么看起来就不会发生任何事情.但是,检查任务管理器会显示新实例正在作为后台进程运行.如果我尝试启动客户端应用程序的另一个新实例,它将显示我写的错误屏幕 - 说明服务的错误.调查显示客户端无法创建服务回调通道的新实例,因为另一个应用程序已经注册了URL.这是一个System.ServiceModel.AddressAlreadyInUseException.
如果我然后在任务管理器中结束后台客户端任务,则显示错误消息的客户端可以连接到服务并正常运行.我还注意到,如果在启动新实例之前关闭后台任务,则新实例也不会出现.
我担心的是,这是不可用的,对用户来说感觉真的很麻烦.怎么可能出错?似乎有些事情没有清理非托管资源但是我使用了ANTS并且无法识别它.客户端创建为:
IServiceCallback callback = new Callback();
_context = new InstanceContext(callback);
_channelFactory = new DuplexChannelFactory<IMyService>(_context, binding, endpoint);
_proxy =
_channelFactory.CreateChannel();
((ICommunicationObject)_proxy).Open(TimeSpan.FromSeconds(5));
Run Code Online (Sandbox Code Playgroud)
Service的构造函数使用以下代码:
_callback = OperationContext.Current.GetCallbackChannel<IServiceCallback>();
var commObject = _callback as ICommunicationObject;
if (commObject != null)
{
commObject.Faulted += ChannelFaulted;
commObject.Closing += ChannelClosing;
commObject.Closed += ChannelClosed;
}
OperationContext.Current.Channel.Faulted += ChannelFaulted;
OperationContext.Current.Channel.Closed += ChannelFaulted;
Run Code Online (Sandbox Code Playgroud)
在关闭之前,客户端调用服务的Disconnect方法,该方法执行以下操作:
var commObject = _callback as ICommunicationObject;
if (commObject != null)
{
commObject.Faulted -= ChannelFaulted;
commObject.Closing -= ChannelClosing;
commObject.Closed -= ChannelClosed;
}
OperationContext.Current.Channel.Faulted -= ChannelFaulted;
OperationContext.Current.Channel.Closed -= ChannelFaulted;
Run Code Online (Sandbox Code Playgroud)
最后,客户端关闭这样的渠道:
foreach (var incomingChannel in _context.IncomingChannels.ToArray())
{
incomingChannel.Close();
}
try
{
var proxy = _proxy as IChannel;
if (proxy != null)
{
proxy.Close();
}
}
catch (Exception)
{
_channelFactory.Abort();
}
Run Code Online (Sandbox Code Playgroud)
为什么我会看到这种不寻常的行为?是否有一些我缺少关闭频道或我做错了什么来创建它?或者是否可能在我的代码中的其他地方存在一个问题,使通道或会话保持活动状态?
**更新:**我一直在尝试一些事情,并发现如果我启动一个客户端实例,关闭它,然后保持一个小时,我可以启动另一个实例没有问题.我还发现如果在创建和关闭客户端应用程序的实例后重新启动Windows服务,那么我也可以在这些情况下创建另一个.
**更新2:**单步执行,我可以看到incomingChannel.Close()没有完成,也没有抛出错误.我删除了该部分,也发现proxy.Close()没有完成,也没有抛出异常.我尝试使用重载并添加了超时,但没有抛出超时异常.Service的Dispose()方法根本没有被击中.
| 归档时间: |
|
| 查看次数: |
448 次 |
| 最近记录: |