运行对象可以被垃圾收集吗?

Kug*_*gel 1 c#

我有一个简单的课程:

public class Runner
{
    public void RunAndForget(RunDelegate method)
    {
        ThreadPool.QueueUserWorkItem(new WaitCallback(Run), method);
    }

    private void Run(object o)
    {
        ((RunDelegate )o).Invoke();
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我这样使用它:

private void RunSomethingASync()
{
    Runner runner = new Runner();
    runner.FireAndForget(new RunDelegate(Something));
}
Run Code Online (Sandbox Code Playgroud)

这样使用它有危险吗?我的C++胆量告诉我在RunSomethingASync完成后应该销毁runner对象.我对吗?那么在不同线程上运行的方法会发生什么?

或者也许是另一种方式,不会收集跑步者?考虑到我可能多次调用RunSomethingASync(),这将是一个问题.

Ada*_*son 8

我的C++胆量告诉我在RunSomethingASync完成后应该销毁runner对象.我对吗?

简而言之,没有..NET垃圾收集不是在确定的基础上完成的.一旦对象不再有根,就有资格进行垃圾收集 - 也就是说,一旦没有更多的对象(来自生活对象)的引用路径存在.不能保证任何特定的对象 - 或者实际上任何对象 - 都会被垃圾收集,尽管它很可能.

但是,在您的情况下,您的对象甚至不符合条件.虽然对象超出了代码中的范围(因此看起来似乎没有引用),但委托确实包含对其拥有实例的引用(假设它们指向实例方法).在Run调用之前,对对象的引用将一直存在,因为在此之前,该对象将ThreadPool持有对该委托的引用,并且该委托具有对该对象的引用Runner.

所以,回答你的问题,你所做的事情没有危险.由于委托引用了实例,因此在操作完成之后,您的对象将无法也不会被收集.完成后,您的对象将符合条件.


kem*_*002 5

在对象不再被root化之前,它不会被垃圾收集 - 也就是说,直到对它的所有可到达引用都被删除.这有一个例外,如果两个对象彼此保持引用而没有其他任何东西保存对这些对象的引用,那么这两个对象可用于垃圾收集.像你这样运行异步方法会保存对象的引用,并且不会在调用期间处理.

下面注释的注释:在方法上调用Dispose()不会强制该对象上的垃圾收集.

由于我们在谈论垃圾收集,这里是GC.Collect功能的链接:http: //msdn.microsoft.com/en-us/library/xe0c2357.aspx

和GC类本身:http:
//msdn.microsoft.com/en-us/library/a0fwz4wc(v = VS.100).aspx

编辑:请参阅Adam关于委托和对象引用的答案.

  • 这不是很有帮助.这是一个众所周知的事实.在我的情况下谁持有我创建的Runner对象的引用? (2认同)
  • "直到所有对它的引用都被删除":这不完全正确......如果A和B互相引用,但它们没有在其他任何地方引用,它们就有资格进行垃圾收集.它不依赖于对象的引用是否存在,而是取决于对象是否可访问 (2认同)