标签: finalizer

(.net)CriticalFinalizerObject - 它到底做了什么?

我对这个类的理解是,当你想要确保调用Finalizer(析构函数)或类时,你应该使用它,但是从我做过的几个测试中,它似乎不是真的.如果它不能确保调用dispose方法,还有其他方法吗?例如,如果我想确保运行一些代码来结束我的对象,即使我通过任务管理器关闭我的程序或什么?

.net c# vb.net dispose finalizer

6
推荐指数
2
解决办法
2859
查看次数

Java GC问题:当一个对象的某个方法仍在执行时,它怎么会变得无法访问?

我一直在阅读这些关于Java终结器的幻灯片.在其中,作者描述了一个场景(在幻灯片33上),该场景CleanResource.finalize()可以由终结器线程运行,同时CleanResource.doSomething()仍然在另一个线程上运行.怎么会发生这种情况?

如果doSomething()是非静态方法,那么执行该方法某人,某处必须有一个强引用它...对吗?那么在方法返回之前如何清除这个引用呢?另一个线程可以突然进入并将该引用置空吗?如果发生这种情况,doSomething()仍会在原始线程上正常返回?

这就是我真正想知道的,但是对于一个非常超越的答案,你可以告诉我为什么doSomething()幻灯片38比doSomething()幻灯片29 更好.为什么仅仅调用这个keepAlive()方法就足够了?你不需要把整个电话包裹myImpl.doSomething()在一个synchronized(this){}街区吗?

java garbage-collection memory-management finalizer

6
推荐指数
1
解决办法
466
查看次数

任何人都可以解释这种最终化行为

虽然"调查"最终确定(阅读:尝试愚蠢的事情)我偶然发现了一些意想不到的行为(至少对我来说).

我原本期望Finalize方法不被调用,而它被调用两次

class Program
{
    static void Main(string[] args)
    {
        // The MyClass type has a Finalize method defined for it
        // Creating a MyClass places a reference to obj on the finalization table.
        var myClass = new MyClass();

        // Append another 2 references for myClass onto the finalization table.
        System.GC.ReRegisterForFinalize(myClass);
        System.GC.ReRegisterForFinalize(myClass);
        // There are now 3 references to myClass on the finalization table.

        System.GC.SuppressFinalize(myClass);
        System.GC.SuppressFinalize(myClass);
        System.GC.SuppressFinalize(myClass);

        // Remove the reference to the object.
        myClass = null;

        // Force the …
Run Code Online (Sandbox Code Playgroud)

c# clr destructor .net-4.0 finalizer

6
推荐指数
3
解决办法
1015
查看次数

如何在Java中标记为最终化的对象(以便第二次不调用finalize方法)?

主要问题在于主题,但是让我展示我对Java中最终化过程的看法,以便我可以向您提出更多要求.

那么gc通过标记所有活动对象来启动垃圾收集.当所有可到达的对象都标记为"实时"时.所有其他对象都无法访问.下一步是检查每个无法到达的对象,并确定它是否可以立即进行清理,或者应该首先完成.如果对象的finalize方法有一个主体,那么gc会想到下一个方法,那么这个对象是可以最终确定的并且应该最终确定; 如果对象的finalize方法有一个空体(protected void finalize(){})那么它不能最终化并且现在可以被gc清理.(我是对的吗?)
所有可终结的对象将放在同一个队列中,以便稍后逐一完成.据我所知,可终结的对象可以花费大量时间放在队列中,同时等待轮到他们完成.这可能发生,因为通常只有一个名为Finalizer的线程从队列中获取对象并调用它们的finalize方法,当我们在某个对象的finalize方法中有一些耗时的操作时,队列中的其他对象将等待很长时间才能完成.好的,当一个对象完成后,它被标记为FINALIZED并从队列中删除.在下一个垃圾收集过程中,收集器将看到此对象无法访问(再次)并且具有非空的finalize方法(再次),因此该对象应该被放入队列中(再次) - 但它不会因为收集器以某种方式看到这个对象被标记为FINALIZED.(这是我的主要问题:这个对象被标记为FINALIZED的方式,收集器如何知道该对象不应该再次终结?)

java garbage-collection finalize finalization finalizer

6
推荐指数
1
解决办法
1246
查看次数

需要在使用TcpClient的类上实现终结器吗?

我有一个类(比如说MyClass)使用(作为私有字段)一个TcpClient对象.MyClass实现IDisposable调用TcpClient.CloseDispose方法.

我的问题是MyClass还应该实现一个终结器来调用Dispose(bool Disposing)释放TcpClient’s非托管资源,以防MyClass.Dispose调用代码没有调用?

谢谢

c# idisposable finalizer unmanagedresources

5
推荐指数
1
解决办法
883
查看次数

当一个对象超出.Net的范围时,可以运行代码吗?

一旦变量失去.Net语言的范围,有没有办法"自动"运行终结/析构函数代码?在我看来,由于垃圾收集器在不确定的时间运行,因此一旦变量失去范围,析构函数代码就不会运行.我意识到我可以从IDisposable继承并在我的对象上显式调用Dispose,但我希望可能有更多不干涉的解决方案,类似于non.Net C++处理对象破坏的方式.

期望的行为(C#):

public class A {
    ~A { [some code I would like to run] }
}

public void SomeFreeFunction() {
    SomeFreeSubFunction();
    // At this point, I would like my destructor code to have already run.
}

public void SomeFreeSubFunction() {
    A myA = new A();
}
Run Code Online (Sandbox Code Playgroud)

不太理想:

public class A : IDisposable {
    [ destructor code, Dispose method, etc. etc.]
}

public void SomeFreeFunction() {
    SomeFreeSubFunction();
}

public void SomeFreeSubFunction() {
    A myA = new A();
    try { …
Run Code Online (Sandbox Code Playgroud)

.net finalizer

5
推荐指数
1
解决办法
144
查看次数

是什么让终结者如此昂贵?

来自Effective Java:

哦,还有一件事:使用终结器会有严重的性能损失.在我的机器上,创建和销毁一个简单对象的时间约为5.6 ns.添加终结器可将时间增加到2,400 ns.换句话说,使用终结器创建和销毁对象的速度大约低430倍.

是什么让终结者如此昂贵?

java finalizer

5
推荐指数
2
解决办法
394
查看次数

在最终确定时存储'this'

如何定义在类定型期间存储'this'的代码?垃圾收集器应该如何表现(如果在某处定义)?

在我看来,GC应该多次完成类实例,并且以下测试应用程序将打印"66",但终结器只执行一次,导致应用程序打印"6".

几行代码:

using System;

namespace Test
{
    class Finalized
    {
        ~Finalized()
        {
            Program.mFinalized = this;
        }

        public int X = 5;
    }

    class Program
    {
        public static Finalized mFinalized = null;

        static void Main(string[] args)
        {
            Finalized asd = new Finalized();
            asd.X = 6;
            asd = null;
            GC.Collect();

            if (mFinalized != null)
                Console.Write("{0}", mFinalized.X);

            mFinalized = null;
            GC.Collect();

            if (mFinalized != null)
                Console.Write("{0}", mFinalized.X);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我要做的是了解终结器如何管理实例内存.在我的应用程序中可能希望再次重用实例引用以进行进一步处理.

很明显终结器不会"释放"内存(至少在我的测试应用程序中).可以将内存块重用于其他目的吗?甚至解放了?如果不是,那会是内存泄漏还是什么?

现在,我比以前更困惑了.

c# garbage-collection finalizer .net-2.0

5
推荐指数
1
解决办法
89
查看次数

使用多个相关的可终结对象实现可终结的配置模式

我非常熟悉非终结类型的Dispose模式,例如,包含我们想要进行确定性清理的某种托管资源的类型.这些类型通常不实现终结器,因为它完全没有必要.

但是,我正在为本机API实现一个C#包装器,其中包含多个相关的非托管资源,并且看起来需要多个类,每个类都实现了finalizable-dispose模式.问题是配置模式的指导方针说最终的A不应该依赖于最终的B,这正是我需要的:

在MSDN上配置模式:

X不要在终结器代码路径中访问任何可终结的对象,因为它们已经完成的风险很大.

例如,具有对另一个可终结对象B的引用的可终结对象A不能在A的终结器中可靠地使用B,反之亦然.终结器以随机顺序调用(缺少关键终结的弱排序保证).

所以这是我的约束:

  • 要做任何事情,我必须创建一个"API"句柄.
  • 要创建"子"句柄,我必须在"创建子"调用中提供API句柄.
  • 两种类型的句柄都不会泄露.
  • 如果关闭API句柄,则隐式关闭其所有子句柄.
  • 要关闭子句柄,我必须在本机调用中提供子句柄和API句柄.

本机API看起来像这样:

APIHANDLE GizmoCreateHandle();

CHILDHANDLE GizmoCreateChildHandle( APIHANDLE apiHandle );

GizmoCloseHandle( APIHANDLE apiHandle );

GizmoCloseChildHandle( APIHANDLE apiHandle, CHILDHANDLE childHandle);
Run Code Online (Sandbox Code Playgroud)

对此的天真方法将分为两部分:

  • 对于API句柄,请遵循典型的SafeHandle模式.
  • 对于子句柄,请遵循典型的SafeHandle模式,但稍微修改一下,因为子句柄需要对API句柄的引用才能实现其ReleaseHandle覆盖 - 添加一个方法,为子SafeHandle提供API句柄它已经建成了.

所以一切都看起来像这样:

    [DllImport( "gizmo.dll" )]
    private static extern ApiSafeHandle GizmoCreateHandle();

    [DllImport( "gizmo.dll" )]
    private static extern void GizmoCloseHandle( IntPtr apiHandle );

    [DllImport( "gizmo.dll" )]
    private static extern ChildSafeHandle GizmoCreateChildHandle(ApiSafeHandle apiHandle);

    [DllImport( "gizmo.dll" )]
    private static extern void GizmoCloseChildHandle( ApiSafeHandle apiHandle, IntPtr childHandle );

    [DllImport( "gizmo.dll" …
Run Code Online (Sandbox Code Playgroud)

.net c# pinvoke idisposable finalizer

5
推荐指数
1
解决办法
745
查看次数

在具有Finalizer的类上调用.Dispose()

根据Essential C#6.0,你应该:

AVOID在拥有终结器的拥有对象上调用Dispose().相反,依靠终结队列来清理实例.

  1. 有人可以详细说明这一点,因为我不清楚Dispose的重点是什么,如果我们不从拥有的对象中调用它?
  2. 除了Reflection之外,你怎么知道对象是否有Finalizer
  3. 除了搜索API文档(如果您可以访问它并且存在)或者反射之外,您如何知道何时调用Close()/ Close()+ Dispose()?对于非常具体的类型(MemoryStream/ Form/ SqlConnection/ etc),我在网络上看到了很多问题,但我更关注"如何自己解决".

根据Dispose Pattern你应该:

除了Dispose()之外,CONSIDER提供方法Close(),如果close是该区域中的标准术语.这样做时,将Close实现与Dispose相同并考虑显式实现IDisposable.Dispose方法非常重要.

但有时候你应该像两个人一样打电话Form等.像" 关闭和处理 - 要打电话的人? "这样的问题越来越接近,但除此之外没有明确的方法

像往常一样答案是:这取决于.不同的类以不同的方式实现IDisposable,由您来做必要的研究.

编辑:这是完整的指南,我没有要求复制许可,但因为它是一个指南(因此假设它应该是自由共享的公共知识)而不是实际培训材料的某些部分,我希望我'我没有违反任何规则.

准则
DO仅对具有稀缺或昂贵资源的对象实施终结器方法,即使最终化延迟了垃圾收集.
实现IDisposable以支持具有终结器的类的确定性终结.
如果没有显式调用Dispose(),请对实现IDisposable的类实现终结器方法.
DO重构一个finalization方法来调用与IDisposable相同的代码,也许只是调用Dispose()方法.
不要从终结器方法中抛出异常.
从Dispose()调用System.GC.SuppressFinalize()以避免重复资源清理并延迟对象上的垃圾回收.
确保Dispose()是幂等的(应该可以多次调用Dispose()).
保持Dispose()简单,专注于最终化所需的资源清理.
AVOID在拥有终结器的拥有对象上调用Dispose().相反,依靠终结队列来清理实例.
避免引用在最终确定期间未完成的其他对象.
在重写Dispose()时,请调用基类的Dispose()方法.
在调用Dispose()之后,考虑确保对象变得不可用.在处理了一个对象之后,Dispose()以外的方法(可能被多次调用)应抛出一个ObjectDisposedException.
在具有一次性字段(或属性)的类型上实现IDisposable并处理所述实例.

c# dispose finalizer

5
推荐指数
1
解决办法
420
查看次数