WCFを使用して他のサービスに接続するWindowsサービスがあります。それらが生存していることをチェックし、これらのサービスが持つエラーメッセージを取得し、これらのレポートを報告します。これは、チャネルファクトリを使用して30秒ごとにチェックされます。チャネルファクトリを使用すると、インターフェイスに準拠するコンフィギュレーション内で見つかったサービスごとにプロキシが作成されます。うまく動作してから数日が経過すると、サーバーは応答しなくなり、「RPC Server Unavailable Error」の報告を開始します。私はそれに接続するためにコンピュータの管理を使用することができ、メモリフットプリントは登るようには見えませんが、サービスを停止すると問題は完全に修正されます。私が使用しているチャンネルファクトリマネージャーを添付しましたが、他に必要なものがあれば教えてください。サービスチャネルが正しく解放されていない可能性はありますか?これを診断するには何ができますか?誰もこれを前にして来たのですか?WindowsサービスがWCFを呼び出すことによって発生する「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();
}
}
}
}
おかげ ロブ
あなたのディスポーザルコードが期待どおりに機能していないように、あなたが説明している問題は確かに聞こえます。この[Gordian Knot](http://en.wikipedia.org/wiki/Gordian_knot)をカットしたい場合は、静的コレクションを取り除き、必要に応じて各WCFクライアントtry/catchパターン内で各サービスプロキシをインスタンス化してください> try> call> close> catch> abort)を選択します。パフォーマンスは低下しますが、少なくとも、あなたが今行っているようなネットワークリソースが漏れていないかどうかを判断することができます:) –
ありがとうございました。パフォーマンスはそれほど問題にならないはずです。そのようなものはもっと良い賭けになるでしょう。 – bobwah