2011-06-05 124 views
4

最近我注意到我的代碼中使用Reactive Extensions的一個小錯誤。我訂閱了Timer,但我從未處理過訂閱。這導致內存泄漏。Can Observable.Timer()會導致內存泄漏嗎?

我創建片斷這凸顯了這種危險:

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

這是正常的行爲呢?

不應該調度程序持有對定時器的弱引用,以便在訂戶與應用程序的其餘部分失去連接時獲取垃圾回收?

回答

4

這是正常的,並且是特徵

訂閱()的語義是永遠聽,或直到Disposed()或OnCompleted()或OnError(),這是先到先。

5

可以保持到訂閱的引用,即使有CompositeDisposable將它們結合起來,但原本無限運營管理IObservable壽命的常用方法(如Timer)是通過使用適用終止規則操作另一個,如Take(取x值),TakeWhile(取值,f(x)返回true)或TakeUntil(取值直到另一個序列,,發出一個值或完成)。

運行Rx操作員不會自動GC'd,除非他們已完成。例如,Timer/Interval兩者都使用IScheduler遞歸地調度其下一個值,並且各種調度器的默認實例都可以通過Scheduler的靜態屬性來訪問。這使運行的操作員始終紮根,因此無法用於GC。

1

我不同意答案。 當你使用無限循環創建連續的可觀察對象時,你實質上做的事情是多餘的,因此內存泄漏。 刪除while循環,只需要一個Observable.Timer,或者更好地使用Observable.Interval。只有一個例子,當你不需要它時,再打電話處置它。

+0

該代碼是一個簡化的示例代碼,使問題更加明顯。我認爲作者知道你寫的是什麼。 – 2015-07-03 11:11:28