在一个封闭的对象上的垃圾收集

Ada*_*kis 0 c# asp.net garbage-collection c#-4.0

注意以下代码来自asp.net.


如果我有(写得不好)代码如下

AmazonS3 s3Client = Amazon.AWSClientFactory.CreateAmazonS3Client();

// ...
// details elided
// ...

BackgroundWorker worker = new BackgroundWorker();

worker.DoWork += new DoWorkEventHandler((s, args) =>
{
    s3Client.PutObject(titledRequest);
});

new Thread(() => worker.RunWorkerAsync()).Start();
Run Code Online (Sandbox Code Playgroud)

垃圾收集器是否足够智能,永远不会收集s3Client对象,直到后台工作人员完成它为止?


注意,我正在开始一个线程内部的后台工作程序,只是为了修复在我直接关闭后台工作程序时发生的asp.net内引发的恼人错误.

cdh*_*wie 5

是的,它会的.编译器将为您生成一个新类,其中包含您在闭包中引用的每个本地的字段.闭包体将被发射到该类的方法中,并且编译器将重写包含函数中的所有本地,以引用该闭包对象上的字段.

所有这些魔法都发生在编译时; 运行时不需要知道任何有关它的信息.由于运行时已足够智能,不能收集作为委托目标的对象,因此闭包引用的本地生命周期保证延长到生成的委托对象的生命周期.

为了说明,编译器将吐出这样的东西:

[System.Runtime.CompilerServices.CompilerGeneratedAttribute]
internal class ClosureImplementation // See note 1
{
    public AmazonS3 s3Client;

    public void Method(object s, EventArgs args)
    {
        s3Client.PutObject(titledRequest); // See note 2
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,在您的方法中,这将被发出:

ClosureImplementation closure = new ClosureImplementation();
closure.s3Client = Amazon.AWSClientFactory.CreateAmazonS3Client();

// ...

worker.DoWork += closure.Method;
Run Code Online (Sandbox Code Playgroud)

笔记:

  1. 生成的类的名称由编译器选择; ClosureImplementation只是一个例子.
  2. 我没有足够的上下文来知道titledRequest来自哪里,所以我故意没有解决编译器如何处理它.