为了账号安全,请及时绑定邮箱和手机立即绑定

当ViewModel不可见时如何正确处理DispatcherTimer /队列

当ViewModel不可见时如何正确处理DispatcherTimer /队列

C#
波斯汪 2021-04-06 21:18:50
在具有MVVM模式的WPF应用程序中,我有一个DockManager,它根据客户的配置显示不同的窗格。其中一些View / ViewModel使用DispatcherTimer处理来自队列的数据,该数据在经过一段时间并处理队列之后(选择该选项是因为数据以很高的频率处理并且直接绑定到DataItems会降低性能。做一些测试,我发现(这是正确的)即使没有显示View / ViewModel,DispacterTimer也会被调用,并且这占用了主线程上的资源,该资源最好执行其他操作,然后更新无用的ViewModel(因为数据已更新)频繁,因此当用户按顶部的窗格时,更新的数据有99%是旧的)我想知道处理这些数据的最佳方法是什么。乍一看,我想完全跳过更新,然后将其委托给以后的过程(将视图推到顶部时,但是这样,在显示最新数据之前,我将需要做很多工作。我的第一个想法是添加,if(!IsActive) return但这不会处理队列,有什么建议吗?
查看完整描述

2 回答

?
qq_遁去的一_1

TA贡献1725条经验 获得超7个赞

这就是您的管理方式。。。您必须选择在何处处理数据并在ViewModel中进行转换。唯一的事情是在调度程序线程上填充可观察对象。


主视图模型

_UpdateTimerClock = new DispatcherTimer();

_UpdateTimerClock.Interval = new TimeSpan(0, 0, 6);

_UpdateTimerClock.IsEnabled = true;

_UpdateTimerClock.Tick += UpdateTimerClockElapsed;



public void UpdateTimerClockElapsed(object tag, EventArgs args)

{

    try

    {

        Messenger.Default.Send(new NotificationViewModelRefresh());

    }

    catch (Exception err)

    {

        BusinessLogger.Manage(err);

    }

}

子视图模型

public ViewModel()

{

    try

    {

        Messenger.Default.Register<NotificationViewModelRefresh>(this, HandleRefreshAction);

    }

    catch (Exception error)

    {

        BusinessLogger.Manage(error);

    }

}


private void HandleRefreshAction(NotificationViewModelRefresh msg)

{

    if (!this.IsVisible)

        return;

儿童观

public View()

{

    InitializeComponent();


    if (!DesignerProperties.GetIsInDesignMode(this))

    {

        this.IsVisibleChanged += (o, e) =>

        {

            if (this.IsVisible)

                (this.DataContext as ViewModel).Refresh();

        };

    }

}

在计时器中的刷新或更常规的处理任务中...

Task tk = Task.Factory.StartNew(() =>

    {

        if (System.Threading.Monitor.TryEnter(_RefreshLocker))

        {

            try

            {

                VisualHelper.InvokeBackground(() =>

                {

视觉辅助提取物

private static void BeginInvoke(DispatcherPriority prio, Action action)

    {

        try

        {

            if (Application.Current != null)

            {

                if (Application.Current.Dispatcher.CheckAccess())

                    action();

                else

                    Application.Current.Dispatcher.BeginInvoke(prio, (ThreadStart)(() => action()));

            }

        }

        catch (Exception err)

        {

            BusinessLogger.Manage(err);

        }

    }


查看完整回答
反对 回复 2021-04-10
  • 2 回答
  • 0 关注
  • 280 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信