Может Observable.Timer () привести к утечкам памяти? - PullRequest
4 голосов
/ 06 июня 2011

Недавно я заметил небольшую ошибку в моем коде, которая использует Reactive Extensions. Я подписывался на Таймер, но никогда не выбрасывал свою подписку. Это привело к утечке памяти.

Я создал фрагмент, который подчеркивает эту опасность:

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

Это нормальное поведение?

Разве планировщик не должен содержать слабую ссылку на таймер для сбора мусора, когда подписчики теряют связь с остальной частью приложения?

Ответы [ 3 ]

6 голосов
/ 06 июня 2011

Вы можете сохранить ссылку на подписку и даже объединить их с CompositeDisposable, но обычный метод управления временем жизни IObservable для бесконечного оператора (например, Timer)используя оператор, который применяет правила завершения к другому, например, Take (принимать значения x), TakeWhile (принимать значения, когда f(x) возвращает значение true) или TakeUntil (принимать значения до другой последовательности, y , выдает значение или завершает).

Запуск операторов Rx не будет автоматически считываться GC, если они не завершены.Timer / Interval, например, оба рекурсивно планируют свое следующее значение, используя IScheduler, и экземпляры по умолчанию различных планировщиков доступны через статические свойства Scheduler.Это делает работающий оператор всегда укоренившимся и поэтому недоступным для GC.

4 голосов
/ 06 июня 2011

Это нормально, и это функция .

Семантика для Subscribe () - это прослушивание навсегда или до тех пор, пока не произойдет сначала Disposed (), OnCompleted () или OnError ().

1 голос
/ 04 июня 2014

Я не согласен с ответом. То, что вы по существу делаете, является избыточным, поскольку вы используете бесконечный цикл для создания последовательных наблюдаемых, отсюда и утечка памяти. Удалите цикл while и просто используйте один Observable.Timer или, что еще лучше, используйте Observable.Interval. Только один случай, когда он вам больше не нужен, вызовите dispose для него.

...