无法从非托管客户端释放.net服务组件对象(com +)的内存

时间:2011-06-03 09:23:14

标签: c# .net com-interop com+

我已将c#dll暴露为.net服务组件(com +)。它由一个无人管理的客户(Unify Vision)消费。我已在组件服务下部署了此组件。

我将池大小设置为5,将创建时间设置为2分钟。我在服务器模式下运行com +。并将空闲关机时间设置为3分钟。

一切正常,但一旦达到最大池大小(5),进程就会保持活跃状态​​而不会被清理干净。由于这个原因,如果我试图创造一个更多的对象,它的失败和悬挂。

似乎对象没有被消费者释放。此服务组件有两种方法_Destroy和Dispose。一旦使用它,我必须使用哪一个来释放它。此外,在调用这些方法后,对象是否会立即释放。有没有办法找出对象有多少引用?

另外,我是否需要使用JIT之类的东西并设置自动完成属性?我已经尝试过这个选项了。

我不确定对象是否会被释放回池中。如何追踪?

请帮忙

由于 sveerap

1 个答案:

答案 0 :(得分:2)

  

有两种方法_Destroy和   处理由此服务暴露   零件。在使用对象后,我必须使用哪一个来释放它。

由于您正在处理服务器(进程外)应用程序,因此客户端不应该调用Dispose()。如果您的组件配置正确,则dispose将实际创建/激活一个新实例,以便调用Dispose方法。请阅读文章Object Lifetimes中的Understanding Enterprise Services (COM+) in .NET了解全貌。

  

对象是否会被释放   紧接着打电话给这些   方法

是的,它会被退回到游泳池。

  

有没有办法找出多少   引用是否存在于对象中?

使用COM + Explorer查看应用程序中的所有组件。将视图设置为状态,您将看到对象的数量,激活的对象的数量,池化对象的数量以及呼叫时间。

  

另外,我需要使用类似的东西吗?   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之后立即同时调用sleep。

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