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

发布于 2024-11-14 00:36:00 字数 449 浏览 3 评论 0 原文

我已将 c# dll 公开为 .net 服务组件 (com+) 。它正在被无人管理的客户端(Unify Vision)使用。我已将该组件部署在组件服务下。

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

一切工作正常,但一旦达到最大池大小(5),进程就会保持活动状态而不会被清理。因此,如果我尝试再创建一个对象,它就会失败并挂起。

消费者似乎没有释放对象。该服务组件公开了两个方法 _Destroy 和 Dispose。一旦使用了对象,我必须使用哪一个来释放该对象。另外,调用这些方法后对象是否会立即释放。有什么方法可以找出该对象有多少个引用吗?

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

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

请帮忙

谢谢 斯韦拉普

I have exposed c# dll as .net serviced component (com+) . It is being consumed by an unmananged client (Unify Vision). I have deployed this component under component services.

I set the pool size to 5 and the creation time out to 2 minutes. I am running the com+ under server mode. and set the idle shutdown time to 3 minutes.

Everything is working fine but once the max pool size(5) is reached, the processes are staying alive without getting cleaned up. And due to this,if I try to creat one more object ,its failing and hanging.

It seems that objects are not getting released by the consumer. There are two methods _Destroy and Dispose exposed by this serviced component. Which one do I have to use for releasing the object once it is used. Also, will the object get released immediately after the call to these methods. Is there any way to find out how many references are there to the object?

Also, Do I need to use anything like JIT and setting the auto complete attribute?. I already tried this option though.

I am not sure whether the object is getting released back to the pool. How to track this?

Please help

Thanks
sveerap

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

流年已逝 2024-11-21 00:36:00

有两种方法_Destroy和
处置由此服务暴露的
成分。一旦使用了对象,我必须使用哪一个来释放该对象。

由于您正在处理服务器(进程外)应用程序,因此客户端不必调用 Dispose()。如果您的组件配置正确,那么 dispose 实际上会创建/激活一个新实例,只是为了调用 Dispose 方法。在文章 对象生命周期 ://msdn.microsoft.com/en-us/library/ms973847.aspx" rel="nofollow">了解 .NET 中的企业服务 (COM+) 了解完整情况。

对象会被释放吗
在调用这些之后立即
方法。

是的,它将返回到池中。

有什么办法可以知道有多少
是否有对该对象的引用?

使用 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 查看调用顺序。这里有 2 个客户端同时调用,并在调用 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     

There are two methods _Destroy and
Dispose exposed by this serviced
component. Which one do I have to use for releasing the object once it is used.

Since you are dealing with a Server (out of process) Application the client should not have to call Dispose(). If your component is configured properly dispose will actually create/activate a new instance just to invoke the Dispose method. Read about Object Lifetimes in the article Understanding Enterprise Services (COM+) in .NET for a full picture.

will the object get released
immediately after the call to these
methods.

Yes, it will be returned to the pool.

Is there any way to find out how many
references are there to the object?

Use the COM+ Explorer to view all components in your application. Set the view to status and you will get to see the number of objects, the number of activated objects, the number of pooled objects, and the call time.

Also, Do I need to use anything like
JIT and setting the auto complete
attribute?. I already tried this
option though.

Yes, you will have to use JIT and call ContextUtil.DeactivateOnReturn = true;.

I am not sure whether the object is
getting released back to the pool. How
to track this?

You can override the Activate and Deactivate methods to see when your component is removed from the pool and released back to the pool.

Here's an example that has a pool with a maximum number of 1 object but returns the instance to pool immediately after the method call:

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);
        }

    }
}

If you call the Hello method concurrently by multiple clients without releasing the client objects you will see that the method does not block (except for the duration of the call) because the object is released back to the pool after the Hello method returns. Use DebugView to see the sequence of calls. Here are 2 clients calling concurrently with a sleep immediately after the call to 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     
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文