ViewModel 每秒更新一次?
我正在编写一个应用程序,显示用户在课程上的剩余时间列表。 我希望列表每秒动态更新,以便用户获得完整的概述。
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);
}
}
正如您在上面看到的,这个想法是模型知道顾客何时进入赛道以及离开的时间。 正如您所看到的,我正在考虑使用 INotifyPropertyChanged 接口,然后在每个视图模型上实际上都有一个计时器。
然而这是我关心的问题。在每个视图模型上添加计时器似乎非常臃肿,这真的是实现这一目标的最佳方法吗? 第二个问题是,如果计时器永远不会停止,这是否会导致内存泄漏,因为计时器永远不会停止并保持视图模型处于活动状态? 如果是这种情况,我的视图模型还需要实现 IDisposable,并且我需要记住运行所有视图模型并处理它们以确保它们被垃圾收集。我的担忧正确吗?
谢谢。
是的,我正在考虑有一个计时器服务来防止有多个计时器,但是必须手动取消注册肯定会在某些时候引入内存泄漏。
所以弱事件的想法很棒。
我正在考虑这样做:
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
{
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;
}
}
您有什么意见吗? 我知道我可以使用单例 GetInstance(或 IoC),但这只会使其使用起来更加不方便。
我正在使用 Daniel Grunwald 在 codeproject 上编写的 WeakEvent 实现。 (它提供了一个非常干净的类并且没有太多开销)。 http://www.codeproject.com/KB/cs/WeakEvents.aspx
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
{
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以拥有一个带有私有计时器和公共事件的计时器服务,每秒通知所有视图模型。
关于内存问题,您可以在导航页面时向计时器服务注册视图模型(
OnNavigedTo
)并在视图关闭时取消注册(OnNavigedFrom
)。这样,当视图模型超出范围时,它们就不会与计时器服务有任何引用,并且它们将被正确地垃圾收集。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.