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

发布于 2024-12-02 02:16:38 字数 536 浏览 1 评论 0原文

在以下代码中,我在类的构造函数中创建一个 DispatcherTimer。没有人对此进行参考。

根据我的理解,计时器应该在离开构造函数的作用域后一段时间由垃圾收集器回收。 但这并没有发生!即使在使用 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();
        };
    }
}

In the following code, I create a DispatcherTimer in the class's constructor. No one keeps reference on it.

In my understanding, the timer should be reclaimed by the garbage collector some time after leaving the constructor's scope.
But that doesn't happen! Even after forcing a garbage collection with GC.Collect()

What is going on under the hood?

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

倒数 2024-12-09 02:16:38

计时器相当特殊,因为它们通过调用

this.timerRoot = GCHandle.Alloc(this);

一些链接来获取自身

编辑:< br>

没有意识到它是一个 DispatcherTimer - 它不是直接 root 而是间接(到 Dispatcher),这反过来又会导致相同的效果。 。

Timers are rather special since they root themselves by calling

this.timerRoot = GCHandle.Alloc(this);

some links

EDIT:

Didn't realize that it was a DispatcherTimer - that doesn't root itself directly but indirectly (to the Dispatcher) which in turn leads to the same effect...

闻呓 2024-12-09 02:16:38

当您只是构造一个 DispatcherTimer 时,没有什么可以阻止它被 GC 。但是,您设置了 IsEnabled = true,这将在计时器上调用 Start()。当这种情况发生时,这行代码将被执行:

this._dispatcher.AddTimer(this);

现在 Dispatcher 本身正在根计时器,这意味着它无法被 GC 处理。

When you just construct the a DispatcherTimer, nothing prevents it from be GCed. However, you set IsEnabled = true, which will call Start() on the timer. When that, happens, this line of code will be executed:

this._dispatcher.AddTimer(this);

And now the Dispatcher itself is rooting the timer, meaning it can't be GCed.

无所谓啦 2024-12-09 02:16:38

它将被添加到将被扎根的 Dispatcher 队列中。

It will be added to the Dispatcher queue which will be rooted.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文