2013-05-21 77 views
6

我注意到,在我的.NET 3.5應用程序中,它使用ReactiveUI,我有一個重大的內存泄漏,似乎源於ObservableAsPropertyHelper。我創建了一個測試項目來演示它hereReactiveUI ObservableAsPropertyHelper/Reactive Extensions內存泄漏?

看來,每一個簡單的ObservableAsPropertyHelper計算屬性泄漏內存引起的變化通知。泄漏似乎源於Reactive Extensions,而不是直接在ReactiveUI中,但是我使用OAPH非常簡單,我不知道是否有人遇到過這個問題,或者可能有一個建議的修復。

內存泄漏的嚴重程度因.NET 3.5(RxUI 2.4,Rx 1.1)和.NET 4.0(RxUI 4.2,Rx 2.0.3)而異。它與.NET 3.5中的每個屬性更新都非常接近線性。但是,.NET 4.0中的泄漏仍然存在。

我上傳了我的.NET 3.5和.NET 4.0測試會話與測試應用程序here的測試項目和一些分析器圖像。

您可以在圖像中看到對象圖是不同的,所以我們可能會完全討論兩種不同的泄漏。在4.0會話(40_RetentionGraph.png)中,您可以看到最多分配的對象是Ints(我的OAPH屬性的類型)和ConcurrentQueue。那裏似乎有一些循環參考問題。您還可以在40_IntsAllocatedGCRootGrows.png中看到與實例的GC根的距離增加。

在3.5版本(我最關心的)中,可以看到(35_Summary.png)最多分配的對象是Action和ScheduledObserver。對象圖比40版更加複雜和完全不同。

我已閱讀this discussion,但還未找到直接答案:我的方案是,OAPH的更新非常簡單。任何有關這種泄漏可能的解決方案的洞察力,我們感激。

回答

4

您尚未指定調度程序,因此默認情況下RxUI將用於DispatcherScheduler。由於您的應用程序是控制檯應用程序,因此沒有正在運行的分派器。所有這些內存都被OnNext的排隊消費,沒有任何東西可以運行它們。

你可以做手腳發射了一個調度器和餵養它幀運行(其中一個WPF應用程序會爲你做),或用於測試的目的只是改變從這個ReactiveTester構造:

public ReactiveTester() 
{ 
    _Total = this.WhenAny(x => x.A, x => x.B, (a, b) => a.Value + b.Value) 
       .ToProperty(this, x => x.Total); 
} 

對此:

public ReactiveTester() 
{ 
    _Total = this.WhenAny(x => x.A, x => x.B, (a, b) => a.Value + b.Value) 
       .ToProperty(this, x => x.Total, 0, Scheduler.CurrentThread); 
} 

而且一切都會是紅潤的。

+0

是的,我懷疑這是在提交的RxUI錯誤。好工作。 –

+0

你是對的,添加這個解決了測試應用程序中的問題。謝謝詹姆斯和保羅!我想我的後續問題是:什麼可能導致我的WPF應用程序類似的泄漏?我的.WhenAny()是從UI和後臺線程中調用的。我是否需要在每個.ToProperty()調用中明確指定調度程序?如果是這樣,它應該是Scheduler.CurrentThread? –

+1

我猜測沒有看到你的代碼,但我看到你的3.5示例使用RxUI和Rx 1.1。 IIRC,如果您在非UI線程上調用ToProperty()並且未指定調度程序,則該組合將導致創建新的Dispatcher(不會被抽取)。嘗試在分派器上運行您的初始化代碼。 –