Observable.Timer() 会导致内存泄漏吗?

发布于 2024-11-13 19:06:17 字数 296 浏览 3 评论 0原文

最近,我注意到我的代码中使用反应式扩展的一个小错误。我正在订阅 Timer,但我从未放弃我的订阅。这导致了内存泄漏。

我创建了强调这种危险的片段:

while (true)
{
    Observable.Timer(TimeSpan.Zero, TimeSpan.FromMinutes(1)).Subscribe(Console.WriteLine);
}

这是正常行为吗?

当订阅者与应用程序的其余部分失去连接时,调度程序是否应该保留对计时器的弱引用以对其进行垃圾收集?

Recently I noticed a small bug in my code which uses Reactive Extensions. I was subscribing to Timer but I never disposed my subscription. This resulted in a memory leak.

I created snippet which highlights this danger:

while (true)
{
    Observable.Timer(TimeSpan.Zero, TimeSpan.FromMinutes(1)).Subscribe(Console.WriteLine);
}

Is this normal behaviour?

Shouldn't scheduler hold weak reference to timer to get it garbage collected when subscribers lost connection with the rest of the app?

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

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

发布评论

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

评论(3

笔芯 2024-11-20 19:06:18

可以保留对订阅的引用,甚至可以将它们与CompositeDisposable结合起来,但是管理IObservable生命周期的常用方法是无限的运算符(如 Timer)是通过使用将终止规则应用于另一个运算符的运算符,如 TakeWhile(获取 x 值)、TakeWhile(获取值) while f(x) 返回 true)或 TakeUntil(获取值,直到另一个序列 y 发出值或完成)。

正在运行的 Rx 运算符不会自动被 GC 处理,除非它们已完成。例如,Timer / Interval 都使用 IScheduler 递归地调度其下一个值,并且各种调度程序的默认实例都可以通过静态访问调度程序的属性。这使得正在运行的操作员始终处于 root 状态,因此无法进行 GC。

You can keep a reference to the subscription, and even combine them with a CompositeDisposable, but the usual method of managing IObservable lifetime on an otherwise infinite operator (like Timer) is by using an operator that applies termination rules to another, like Take (take x values), TakeWhile (take values while f(x) returns true) or TakeUntil (take values until another sequence, y, emits a value or completes).

Running Rx operators won't be automatically GC'd unless they've completed. Timer / Interval, for example, both recursively schedule their next value using an IScheduler and the default instances of the various schedulers are all accessible via static properties of Scheduler. This makes the running operator always rooted and therefore unavailable for GC.

中二柚 2024-11-20 19:06:18

这是正常现象,并且是一个功能

Subscribe() 的语义是永远监听,或者直到 Dispose() 或 OnCompleted() 或 OnError()(以先到者为准)。

This is normal, and is a feature.

The semantics for Subscribe() are listen forever, or until Disposed() or OnCompleted(), or OnError(), which ever comes first.

乖不如嘢 2024-11-20 19:06:18

我不同意这个答案。
您本质上所做的事情是多余的,因为您使用无限循环来创建连续的可观察量,因此会导致内存泄漏。
删除 while 循环,只使用一个 Observable.Timer,或者更好地使用 Observable.Interval。只有一个实例,然后当您不再需要它时,调用 dispose 即可。

I don't agree with the answer.
What you're essentially doing is redundant as you're using an infinite loop to create successive observables, hence the memory leak.
Remove the while loop and just have one Observable.Timer or even better use an Observable.Interval. Just one instance then when you don't need it anymore call dispose on it.

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