Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
构造函数中声明的C#对象的垃圾回收_C#_.net_Constructor_Garbage Collection - Fatal编程技术网

构造函数中声明的C#对象的垃圾回收

构造函数中声明的C#对象的垃圾回收,c#,.net,constructor,garbage-collection,C#,.net,Constructor,Garbage Collection,在下面的代码中,我在类的构造函数中创建了一个Dispatchermer。没有人在上面保留参考资料 在我的理解中,计时器应该在离开构造函数的作用域后由垃圾收集器回收。 但那不会发生!即使在使用GC.Collect() 引擎盖下发生了什么 public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); new DispatcherTimer

在下面的代码中,我在类的构造函数中创建了一个Dispatchermer。没有人在上面保留参考资料

在我的理解中,计时器应该在离开构造函数的作用域后由垃圾收集器回收。 但那不会发生!即使在使用
GC.Collect()

引擎盖下发生了什么

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        new DispatcherTimer
        {
            Interval = TimeSpan.FromMilliseconds(100),
            IsEnabled = true
        }
        .Tick += (s, e) =>
        {
            textBlock1.Text = DateTime.Now.ToString();
        };
    }
}

计时器非常特殊,因为它们通过调用

this.timerRoot = GCHandle.Alloc(this);
一些链接

编辑:


没有意识到它是一个
调度程序
——它不是直接地,而是间接地(对
调度程序
)进行根处理,这反过来会产生同样的效果…

它将被添加到将被根处理的
调度程序
队列中

当您仅构建a
Dispatchermer
时,没有什么可以阻止它被GCed。但是,您可以设置
IsEnabled=true
,这将在计时器上调用
Start()
。发生这种情况时,将执行以下代码行:

this._dispatcher.AddTimer(this);

现在,
调度程序
本身正在为计时器设置根,这意味着它不能被GCed。

调度程序是否遵循与线程相同的垃圾收集规则。计时器?如果是这样,没有对计时器的字段引用(仅本地引用)将导致垃圾回收本身…但我认为Dispatchermers不是这样的…@JeffN825所有对象都受相同的GC规则约束:如果无法从GC根目录访问,则可以使用GC。在本例中,该代码甚至不是来自正确的timer类。@dlev只是没有意识到它是一个Dispatchermer-请参阅我的EDITMy。我的观点是一个局部范围的线程。只有一个局部引用的timer不是根线程…因此将在没有任何滴答声的情况下进行GC。@JeffN825这并不总是正确的。。。因为计时器可以直接或间接地“根自身”。。。我没有检查Threading.Timer源(通过Reflector),但它在内部调用了TimerBase.AddTimer,这似乎创建了一个引用,即使对于本地范围的计时器也是如此。。。所以它也很可能“间接地植根于”你的场景中。。。