我在控制台应用中托管了一个非常小的wcf服务。
[ServiceContract]
public interface IService1
{
[OperationContract]
void DoService();
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
public class Service1 : IService1
{
public void DoService()
{
}
}
并将其称为
using (ServiceReference1.Service1Client client = new ServiceReference1.Service1Client())
{
client.DoService(new DoServiceRequest());
client.Close();
}
请记住,该服务是在basicHttpBindings上发布的。
问题
现在当我在1000循环中执行上面的客户端代码时,我发现“所有堆字节”和“私有字节”性能计数器(我使用.net内存分析器)之间存在很大差异。经过调查,我发现一些物体没有妥善处理 以下是这些对象的列表(找到了1000个未发现的实例 - >等于客户端调用)
(所有这些的名称空间是System.ServiceModel.Channels)
HttpOutput.ListenerResponseHttpOutput.ListenerResponseOutputStream
BodyWriterMessage
BufferedMessage
HttpRequestContext.ListenerHttpContext.ListenerContextHttpInput.ListenerContextInputStream
HttpRequestContext.ListenerHttpContext
问题 为什么我们有很多不受约束的对象以及如何控制它们。
请帮助
答案 0 :(得分:4)
您正在为每次调用请求一个新实例(InstanceContextMode = InstanceContextMode.PerCall)。如果1000次调用中没有发生GC,则将取消收集服务实例。 WCF要求您实现IDisposable
来自MSDN : Discover Mighty Instance Management Techniques For Developing WCF Apps
每次通话服务 每次调用服务是Windows Communication Foundation的默认实例化模式。为每次调用激活配置服务类型时,服务实例(公共语言运行时(CLR)对象)仅在客户端调用正在进行时存在。每个客户端请求都会获得一个新的专用服图2说明了这种单呼叫激活的工作原理。
Figure 2 Per-Call Instantiation http://i.msdn.microsoft.com/cc163590.fig02(en-us).gif
答案 1 :(得分:1)
您是否有机会启用性能计数器?如下所示?
<system.serviceModel>
<diagnostics performanceCounters="All" />
..
</system.serviceModel>
在“增加性能计数器的内存大小”一节中,从以下链接: http://msdn.microsoft.com/en-us/library/ms735098.aspx
在启用WCF性能计数器时,会提到“流氓”私有字节数。将其更改为ServiceOnly或完全禁用它(关闭)可能会有效。
答案 2 :(得分:0)
我在2010年找到了解决方案,但我忘了发布它。我实际上失去了确切的轨道,但我记得它是.Net库错误,它被报告给微软并得到了他们的认可。我没有链接但我会在找到它后立即发布。无论如何,微软已经在.net 4.0中修复了这个问题,这就是我所遵循的确切解决方案,我知道有些人可能因为服务器环境的改变而有时无法掌握。