在 .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 :
程序.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();
}
}
演示服务.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;
}
}
客户端.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();
}
)
}
有人可以解释这种行为吗?
请注意,我对找到避免泄漏的方法不感兴趣(我已经知道如何做到这一点),而是在解释中(即为什么会发生)。