Прошло некоторое время, и по крайней мере одна вещь по-прежнему не покрыта, поэтому позвольте мне добавить к тому, что сказал Говерт.
Вы спросили:
public class TickerDisposable : IDisposable
{
public void Dispose()
{
// What to do here?
}
}
Давайте подведем итог:
Для каждого нового абонента к вашей тактовой линеечке, Подписаться будет называться на TickerObservable. Поэтому для каждого абонента ваш код создаст новый System.Timers.Timer
и новый обработчик событий timer.Elapsed
- чтобы получить ваш предполагаемый эффект. И это на самом деле все то, что вам нужно, чтобы получить эффект.
Однако вы также должны вернуть IDisposable, поэтому вы создали фиктивный TickerDisposable исключительно для этой цели, и вы не знаете, для чего он предназначен.
Ответ:
IDisposable, что библиотека требует, чтобы вернуться из Subscribe есть только позволит вам после очистки вашего блеска перестает светить. Таймеры - это «системная вещь». Создав их и запустив, они запустите. Через час они не могут быть GC'ed, потому что они должны быть бежать, пока вы их не остановите.Разумеется, вы + = 'ed обработчик событий, наблюдатель (если слабая ссылка) может быть уже мертв, но ваш таймер не знает! Вы должны остановить его в какой-то момент.
Следовательно, шаблон, связанный с IDisposable, заимствованный из RX: любой тяжелый или долгоживущий, который вы выделяете, резервируете, создаете и т. Д. В методе Subscribe, помещайте в него примечание об этом (ваш!) IDisposable. Затем, когда наблюдатель отменит подписку, ваш IDisposable также будет очищен, а ваш пользовательский метод Dispose будет запущен, который сможет просматривать содержимое вашего IDiposable и .. очистить мусор, или, скорее, разблокировать его, поэтому GC может их смыть.
Завершение ваш пример:
public class TickerObservable : IExcelObservable
{
public IDisposable Subscribe(IExcelObserver observer)
{
var timer = new System.Timers.Timer();
timer.Interval = 1000;
timer.Elapsed += (s, e) => observer.OnNext(DateTime.Now.ToString());
timer.Start();
return new TickerDisposable(timer);
}
}
public class TickerDisposable : IDisposable
{
private Timer ticky;
public TickerDisposable(Timer timer)
{
ticky = timer;
}
public void Dispose()
{
if(ticky != null)
ticky.Dispose(); // or Stop, or etc..
}
}
Приведенный выше пример является фактически наиболее очевидным использование возвращенного IDisposable. Однако вы можете использовать его для любого регистрационно-регистрационного уведомления. Например, один общий таймер, он может выглядеть следующим образом:
public class TickerObservable : IExcelObservable
{
private static Timer timer = ..... ; // assume it is up & running & shared
public IDisposable Subscribe(IExcelObserver observer)
{
ElapsedEventHander hd = (s, e) => observer.OnNext(DateTime.Now.ToString());
timer.Elapsed += hd;
return new TickerDisposable(timer, hd);
}
}
public class TickerDisposable : IDisposable
{
private Timer ticky;
private ElapsedEventHander handler;
public TickerDisposable(Timer timer, ElapsedEventHander hd)
{
ticky = timer;
handler = hd;
}
public void Dispose()
{
if(ticky != null && handler != null)
ticky.Elapsed -= handler;
}
}
И теперь вы совершенно уверены, что никакие мертвые-обработчики не задерживаясь на долгоживущих-разделяемой таймера. (конечно, очистка таймера здесь отсутствует, но это еще одна вещь ..). Возможно, у вас уже есть идея, так что получайте удовольствие!