无法从非托管客户端释放.net服务组件对象(com+)的内存
本文关键字:对象 组件 服务组 com+ 内存 服务 net 释放 客户端 | 更新日期: 2023-09-27 17:58:15
我已经将c#dll公开为.net服务组件(com+)。它正被一个未授权的客户端(Unify Vision)使用。我已经在组件服务下部署了这个组件。
我将池大小设置为5,创建时间设置为2分钟。我正在服务器模式下运行com+。并将怠速停机时间设置为3分钟。
一切都很好,但一旦达到最大池大小(5),进程就会保持活力而不会被清理。正因为如此,如果我试图再创造一个物体,它就会失败并挂起。
消费者似乎没有释放物品。此服务组件公开了两种方法_Destory和Dispose。一旦物体被使用,我必须使用哪一个来释放它。此外,在调用这些方法之后,对象会立即被释放吗。有没有办法找出这个对象有多少引用?
另外,我需要使用JIT和设置自动完成属性之类的东西吗?。不过我已经试过了。
我不确定这个物体是否会被放回游泳池。如何跟踪?
请帮助
谢谢sveerap
有两种方法_Destory和处理此服务暴露的组成部分一旦物体被使用,我必须使用哪一个来释放它。
由于您处理的是服务器(进程外)应用程序,客户端不应该调用Dispose()。如果您的组件配置正确,dispose将实际创建/激活一个新实例,只是为了调用dispose方法。请阅读文章《理解.NET中的企业服务(COM+)》中关于对象生命周期的内容,以了解全貌。
这个物体会被释放吗在呼叫这些方法。
是的,它会被送回游泳池。
有没有办法知道有多少对象有引用吗?
使用COM+资源管理器查看应用程序中的所有组件。将视图设置为status,您将看到对象数、激活对象数、池对象数和调用时间。
还有,我需要使用类似的东西吗JIT和设置自动完成属性我已经试过了选项。
是的,您必须使用JIT并调用ContextUtil.DeactivateOnReturn = true;
。
我不确定这个物体是否被释放回游泳池。怎样追踪这个?
您可以覆盖Activate和Deactivate方法,以查看组件何时从池中删除并释放回池。
下面是一个例子,它有一个最大对象数为1的池,但在方法调用后立即将实例返回到池:
using System;
using System.EnterpriseServices;
using System.Runtime.InteropServices;
namespace ClassLibrary1
{
[ComVisible(true)]
[EventTrackingEnabled(true)]
[JustInTimeActivation(true)]
[ObjectPooling(CreationTimeout=60000,
Enabled=true, MaxPoolSize=1, MinPoolSize=0)]
public class Class1 : ServicedComponent
{
public Class1()
{
}
public string Hello()
{
System.Diagnostics.Trace.TraceInformation("Call Hello");
// We are done after this call so return this instance to the pool
ContextUtil.DeactivateOnReturn = true;
return "world";
}
// Get an instance from the pool
protected override void Activate()
{
System.Diagnostics.Trace.TraceInformation("Activated");
base.Activate();
}
// Return an instance to the pool
protected override void Deactivate()
{
System.Diagnostics.Trace.TraceInformation("Deactivate");
base.Deactivate();
}
// Runtime will call Dispose after method call (with disposing = true)
protected override void Dispose(bool disposing)
{
System.Diagnostics.Trace.TraceInformation("Disposing = " + disposing);
base.Dispose(disposing);
}
}
}
如果多个客户端同时调用Hello方法而不释放客户端对象,则会发现该方法不会阻塞(除了调用的持续时间),因为Hello方法返回后对象会被释放回池。使用DebugView查看调用的顺序。这里有两个客户端在呼叫Hello后立即进行睡眠同时呼叫。
00000001 0.00036997 [6068] Activated
00000003 0.00160919 [6068] Call Hello
00000005 0.00493093 [6068] Deactivate
00000007 0.00567035 [6068] Disposing = True
00000009 0.14866389 [6068] Activated
00000011 0.14876986 [6068] Call Hello
00000013 0.14885986 [6068] Deactivate
00000015 0.14896829 [6068] Disposing = True