我有一个使用WCF连接到其他服务的Windows服务。它检查它们是否存活,获取这些服务所具有的任何错误消息,并报告这些消息。使用通道工厂每30秒检查一次,其中为符合接口的配置中找到的每个服务创建代理。运行几天后,服务器无响应,并开始报告“RPC服务器不可用错误”。我可以使用计算机管理连接到它,内存占用打印似乎没有攀爬,但如果我停止服务它完全解决了问题。我已经连接了我正在使用的渠道工厂经理,但是如果需要其他任何东西请告诉我。可能是服务渠道没有正确释放?我该怎么做才能诊断出来?有没有人遇到过这个?
public class ChannelFactoryManager : IDisposable
{
private static Dictionary<Tuple<Type, string>, ChannelFactory> _factories = new Dictionary<Tuple<Type, string>, ChannelFactory>();
private static readonly object _syncRoot = new object();
public virtual T CreateChannel<T>() where T : class
{
return CreateChannel<T>("*", null);
}
public virtual T CreateChannel<T>(string endpointConfigurationName) where T : class
{
return CreateChannel<T>(endpointConfigurationName, null);
}
public virtual T CreateChannel<T>(string endpointConfigurationName, string endpointAddress) where T : class
{
T local = GetFactory<T>(endpointConfigurationName, endpointAddress).CreateChannel();
((IClientChannel)local).Faulted += ChannelFaulted;
return local;
}
protected virtual ChannelFactory<T> GetFactory<T>(string endpointConfigurationName, string endpointAddress) where T : class
{
lock (_syncRoot)
{
ChannelFactory factory;
if (!_factories.TryGetValue(new Tuple<Type, string>(typeof(T), endpointConfigurationName), out factory))
{
factory = CreateFactoryInstance<T>(endpointConfigurationName, endpointAddress);
_factories.Add(new Tuple<Type, string>(typeof(T), endpointConfigurationName), factory);
}
return (factory as ChannelFactory<T>);
}
}
private ChannelFactory CreateFactoryInstance<T>(string endpointConfigurationName, string endpointAddress)
{
ChannelFactory factory = null;
if (!string.IsNullOrEmpty(endpointAddress))
{
factory = new ChannelFactory<T>(endpointConfigurationName, new EndpointAddress(endpointAddress));
}
else
{
factory = new ChannelFactory<T>(endpointConfigurationName);
}
factory.Faulted += FactoryFaulted;
factory.Open();
return factory;
}
private void ChannelFaulted(object sender, EventArgs e)
{
IClientChannel channel = (IClientChannel)sender;
channel.Abort();
}
private void FactoryFaulted(object sender, EventArgs args)
{
ChannelFactory factory = (ChannelFactory)sender;
factory.Abort();
Type[] genericArguments = factory.GetType().GetGenericArguments();
if ((genericArguments != null) && (genericArguments.Length == 1))
{
Type type = genericArguments[0];
string endPointName = factory.Endpoint.Name;
Tuple<Type, string> key = new Tuple<Type, string>(type, endPointName);
if (_factories.ContainsKey(key))
{
_factories.Remove(key);
}
}
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
lock (_syncRoot)
{
foreach (Tuple<Type, string> type in _factories.Keys)
{
ChannelFactory factory = _factories[type];
try
{
factory.Close();
continue;
}
catch
{
factory.Abort();
continue;
}
}
_factories.Clear();
}
}
}
}
由于 罗布
答案 0 :(得分:1)
如果您使用实例化服务代理作为需要路由,则此SO question中的答案提供了处理代理实例的一些选项和基本原理。作为一个基本的开始,我建议:
//Your client type could be ICommunicationObject or ClientBase:
var client = new YourServiceProxyType();
try {
var result = client.MakeCall();
//do stuff with result...
//Done with client. Close it:
client.Close();
}
catch (Exception ex) {
if (client.State != System.ServiceModel.CommunicationState.Closed)
client.Abort();
}
设计一个好的WCF代理处理模式的根本问题是,Microsoft的WCF团队决定以一种可以抛出异常的方式实现Dispose,从而阻止释放非托管资源,直到调用Abort()或代理实例完全垃圾收集。他们编写了框架,以便他们做出选择,不幸的是我们必须承担后果。