【问题标题】:Closure scope and garbage collection闭包作用域和垃圾回收
【发布时间】:2010-10-14 05:20:41
【问题描述】:

如果异步任务处理时间过长,我刚刚编写了一些代码来执行超时操作,但我不清楚是否以及何时处理超时实例(我认为它会在异步任务及时完成的​​情况下完成,否则我不知道),或者我每次调用这段代码时都要累积实例。

//StartNew creates a new instance of System.Timers.Timer, and 
//  invokes the ActionOnTimeout after 2000ms, unless calling code
//  calls "Stop" first
var timeout = ProcessTimeout.StartNew(() => ActionOnTimeout(), 2000);

//DoAsyncTask creates a new thread, does potentially slow stuff, 
///   then invokes this callback
DoAsyncTask(() => 
    {
         if(timeout.Running)
         {
             timeout.Stop();
             DoCallbackStuff();
         }
    });

(如果有帮助,ProcessTimeout 类使用System.Timers.Timer

【问题讨论】:

    标签: c# garbage-collection lambda closures


    【解决方案1】:

    不清楚timeout 在这里是什么或DoAsyncTask 做了什么,但有几点一般性:

    • 您的 lambda 表达式将捕获 timeout 变量。它不会捕获变量的 ...因此,如果您稍后在将 timeout 设置为 null 或其他值的相同方法中有其他内容,则原始值不会是保存在 lambda 表达式中。
    • lambda 表达式阻止 timeout 引用的任何内容被垃圾收集,只要委托本身不符合垃圾收集条件
    • 垃圾收集与处置不同。您谈到“何时处理超时实例” - 什么叫Dispose?这不会受到垃圾收集器的影响,除非您依赖终结器为您调用 Dispose

    【讨论】:

    • 感谢@Jon,我不想复制所有代码,所以我添加了一些关于超时和 DoAsyncTask 的 cmets。当然,关于 GC 和处置,你是对的,尽管我承认我倾向于混淆这两者(为了回答你的问题,没有人打电话给 Dispose - 目前)。这个 sn-p 中对 timeout 的三个引用是唯一使用它的地方。
    • 嗯,所以现在的问题变成了,什么会阻止委托被垃圾收集?我猜如果 DoAsyncTask never 返回没有希望(我可以应付),但是如果它返回“为时已晚”呢?
    • 如果一个作用域包含三个局部变量,其中两个在两个 lambda 表达式中的每一个中使用(其中一个在两个中都使用),并且来自其中一个 lambda 表达式的委托被无限期持有,将未在该 lambda 表达式中使用的变量将继续保留,还是将变量单独保留?
    • @supercat:我相信变量都将保存在一种合成类型中。
    猜你喜欢
    • 1970-01-01
    • 2016-09-19
    • 2015-06-10
    • 1970-01-01
    • 2015-11-13
    • 1970-01-01
    • 1970-01-01
    • 2013-11-16
    相关资源
    最近更新 更多