我有一个 SOA 应用程序,它使用 Windows 服务中托管的双工 WCF 服务。客户端本身是一个 WPF 应用程序。
我在关闭和重新启动客户端应用程序时看到异常行为。如果我在关闭一个实例后启动一个新实例,则似乎什么都没有发生。但是,检查任务管理器显示新实例正在作为后台进程运行。如果我尝试启动客户端应用程序的另一个新实例,它将显示我编写的错误屏幕 - 说明服务错误。调查显示客户端无法创建服务回调 channel 的新实例,因为另一个应用程序已经注册了该 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));
服务的构造函数使用以下代码:
_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;
在关闭之前,客户端调用服务的 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;
最后,客户端像这样关闭 channel :
foreach (var incomingChannel in _context.IncomingChannels.ToArray())
{
incomingChannel.Close();
}
try
{
var proxy = _proxy as IChannel;
if (proxy != null)
{
proxy.Close();
}
}
catch (Exception)
{
_channelFactory.Abort();
}
为什么我会看到这种异常行为?是不是我缺少关闭 channel 的东西,或者我在创建它时做错了什么?还是我的代码中其他地方一定存在使 channel 或 session 保持事件状态的问题?
**更新:** 我一直在尝试一些事情,发现如果我启动一个客户端实例,关闭它,然后将其放置一个小时,我可以毫无问题地启动另一个实例。我还发现,如果我在创建和关闭客户端应用程序的一个实例后重新启动 Windows 服务,那么我也可以在这种情况下创建另一个实例。
**更新 2:** 单步执行,我可以看到 incomingChannel.Close() 没有完成,也没有抛出错误。我已经删除了该部分,还发现 proxy.Close() 没有完成并且没有抛出异常。我试过使用重载并添加了超时,但没有抛出超时异常。服务的 Dispose() 方法根本没有命中。
最佳答案
也尝试关闭您的 channel 工厂。
proxy.ChannelFactory.Close();
proxy.Close();
关于c# - 异常的 WCF 客户端行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25503526/