我有一個使用WCF連接到其他服務的Windows服務。它檢查它們是否還活着,獲取這些服務所具有的任何錯誤消息,並報告這些錯誤消息。每隔30秒使用通道工廠檢查一次,其中爲符合接口的配置中找到的每個服務創建代理。運行好幾天後,服務器變得無響應,並開始報告「RPC服務器不可用錯誤」。我可以使用計算機管理連接到它,它的內存足跡似乎沒有攀升,但如果我停止服務,它完全解決了這個問題。我已附加了我正在使用的渠道工廠經理,但如果需要其他任何內容,請讓我知道。難道服務渠道沒有被正確釋放?我能做些什麼來診斷呢?有沒有人遇到過這個?診斷由Windows服務調用WCF造成的「RPC服務器不可用錯誤」WCF
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();
}
}
}
}
感謝 羅布
您所描述的問題當然聽起來像您的配置代碼沒有按預期工作。如果你想削減這個[Gordian Knot](http://en.wikipedia.org/wiki/Gordian_knot),去掉靜態集合並且在一個好的WCF客戶端中嘗試每個服務代理try/catch模式創建>嘗試>調用>關閉> catch>中止)您的選擇。性能將受到影響,但至少你可以指望不泄漏網絡資源,就好像你現在正在做的那樣:) – 2012-03-19 15:15:19
好的,謝謝我會放棄這一切。性能不應該是那麼大的問題,所以也許這樣做會是一個更好的選擇。 – bobwah 2012-03-19 15:59:11