Iam writing an app that shows a list of the remaining time a user has on a course. I want the list to dynamically update every second so the user has the full overview.
public class ReservationCustomerList : INotifyPropertyChanged
{
public int UnitsLeft { get; set; }
public DateTime? OnCircuitSince { get; set; }
public TimeSpan? TimeLeftDate
{
get
{
if (OnCircuitSince.HasValue)
return TimeSpan.FromSeconds((OnCircuitSince.Value - DateTime.Now).TotalSeconds - UnitsLeft);
return TimeSpan.FromSeconds(UnitsLeft);
}
}
private void FireEverySecond()
{
PropertyChanged.Fire(this, x => x.TimeLeftDate);
}
}
As you can see above the idea is that the model knows when the customer entered the circuit and the time the have left. As you can see iam thinking of using the INotifyPropertyChanged interface and then actually having a timer on every viewmodel.
However this is my concern. Adding a Timer on every viewmodel seems very bloated, is this really the best way to achieve this ? Second concern is that if the timer is never stopped wouldn't this result in a memory leak since the timer would never stop and keep the viewmodel alive ? If this is the case my Viewmodel would also need to implement IDisposable and i would need to remember to run through all viewmodels and dispose them to make sure that these are garbage collected. Are my concerns correct ?
Thanks.
Yes i was thinking of having a timer service to prevent having multiple timers, however having to manually unregister would surely at some point introduce memoery leaks.
So the idea with Weak Events is great.
Iam thinking of doing it something like this:
public class TimerService
{
static Timer Timer;
static FastSmartWeakEvent<EventHandler> _secondEvent = new FastSmartWeakEvent<EventHandler>();
static FastSmartWeakEvent<EventHandler> _minuteEvent = new FastSmartWeakEvent<EventHandler>();
static DateTime LastTime;
public static event EventHandler SecondEvent
{
开发者_JS百科 add { _secondEvent.Add(value); }
remove { _secondEvent.Remove(value); }
}
public static event EventHandler MinuteEvent
{
add { _minuteEvent.Add(value); }
remove { _minuteEvent.Remove(value); }
}
static TimerService()
{
Timer = new Timer(TimerFire, null, 1000, 1000);
}
static void TimerFire(object state)
{
_secondEvent.Raise(null, EventArgs.Empty);
if (LastTime.Minute != DateTime.Now.Minute)
_minuteEvent.Raise(null, EventArgs.Empty);
LastTime = DateTime.Now;
}
}
Do you have any comments ? I Know i could use a singleton GetInstance (or IoC) however this would just make it more inconvinient to use.
Iam using the WeakEvent implementation that Daniel Grunwald wrote on codeproject. (it gives a very clean class and not much overhead). http://www.codeproject.com/KB/cs/WeakEvents.aspx
You could have a timer service with a private timer and a public event, that notifies all the viewmodels every second.
Regarding the memory issues, you could register your viewmodel with the timer service when your page is navigated (OnNavigatedTo
) and unregister it when the view is closed (OnNavigatedFrom
). This way the viewmodels wouldn't have any reference with the timer service when they go out of scope, and they would be garbage collected properly.
精彩评论