.NET / WCF / Windowsサービスでメモリとハンドルのリークを探していると、説明できない奇妙な動作に気づきました。ここにセットアップと解像度があります。私が探しているのは、観察された行動の説明です。
Windowsサービスをインストールしました。
サービスを開始しました。
トランザクションWCF呼び出しを使用して単純なメソッドを呼び出しました(呼び出しごとに新しいチャネル-キャッシュなし)。
呼び出しごとに、約2つのハンドルがメモリに残ります。
これは、次の項目が該当する場合に観察できます。
- これはWindowsサービスです。コンソールアプリとして実行しないでください。
- トランザクション(個別のプロセスまたはマシンでテスト済みのみ)を使用して、WCFメソッドを呼び出します。
ServiceBase.Run(servicesToRun);
あるタイプでインスタンス化XmlSerializerを呼び出す前。- タイプはカスタムタイプです。
new XmlSerializer(typeof(string))
またはnewでは発生しませんXmlSerializer(typeof(XmlDocument))
。シリアル化するための呼び出しは必要ありません。カスタムタイプにプロパティとして文字列しかない場合は十分です(ハンドルはどこにもありません!) - つまり、SGen.exeを使用して静的XmlSerialization.dllを作成しても、この問題は発生しません。
私のコードにはすでに修正が含まれています:
OnStart()で最も早く
XmlSerializerを使用します:
Program.cs
WindowsService winSvc = new WindowsService();
ServiceBase[] servicesToRun = new ServiceBase[]{winSvc};
ServiceBase.Run(servicesToRun);
WindowsService.cs
internal sealed class WindowsService : ServiceBase
{
private ServiceHost wcfServiceHost = null;
internal WindowsService()
{
AutoLog = true;
CanStop = true;
CanShutdown = true;
CanPauseAndContinue = false;
}
internal void StartWcfService()
{
wcfServiceHost = new ServiceHost(typeof(DemoService));
wcfServiceHost.Open();
}
protected override void Dispose(bool disposing)
{
if (wcfServiceHost != null)
{
wcfServiceHost.Close();
}
base.Dispose(disposing);
}
protected override void OnStart(string[] args)
{
new XmlSerializer(typeof(MyType));
StartWcfService();
}
}
DemoService.cs
[ServiceBehavior
(
InstanceContextMode = InstanceContextMode.PerSession,
TransactionAutoCompleteOnSessionClose = false,
IncludeExceptionDetailInFaults = true
)
]
public sealed class DemoService : IDemoService
{
[TransactionFlow(TransactionFlowOption.Allowed)]
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public int Add(int a, int b)
{
return a + b;
}
}
Client.cs:
IChannelFactory<IDemoService> channelFactory = new ChannelFactory<IDemoService>("defaultClientConfiguration");
IDisposable channel = null;
for (int index = 0; index < 5000; index++)
{
using
(
channel = (IDisposable)channelFactory.CreateChannel(new EndpointAddress("net.tcp://localhost:23456/DemoService")))
{
IDemoService demoService = (IDemoService)channel;
using (TransactionScope tx = new TransactionScope(TransactionScopeOption.RequiresNew))
{
demoService.Add(3, 9);
tx.Complete();
}
)
}
誰かがこの振る舞いを説明できますか?
注意してください、私はリークを回避する方法を見つけることに興味がありません(私はすでにこれを行う方法を知っています)が、説明(つまり、なぜそれが起こっているのか)に興味があります。