7

我在外部程序集中有服务类,我将这个类注入到带有 MEF 的视图模型类中。我需要从视图模型每 3-4 秒调用一次服务方法。

我从服务中获得新数据作为字典。此字典绑定到视图中的列表框。我需要在视图中刷新这个数据列表框。

在我的解决方案中,我使用 DispatcherTimer,但我绝对是 calibur.micto 以及 MVVM 和 WPF 的初学者。我不知道在我的情况下什么是合适的解决方案。因此,如果有人有进步,我将不胜感激。

我的解决方案在这里:

[Export("MainScreen", typeof(IMainViewModel))]
    public class MainViewModel : Screen, IMainViewModel
    {

        [Import]
        private Service _service;//import with MEF from external assembly
        [Import]
        private Connection _conn;//import with MEF from external assembly

        //this dictionary is bind to the listbox in view
        private MyObservableDictionary<string, User> _users = null;

        //temp dictionry
        private MyObservableDictionary<string, User> _freshUsers = null;

        private int _selectedUserIndex;

        private DispatcherTimer _dispatcherTimer;


        public Account Account{ get; set;}

        public int SelectedUsersIndex
        {
            get { return _selectedUserIndex; }
            set
            {
                _selectedUserIndex = value;
                NotifyOfPropertyChange("SelectedUsersIndex");
            }
        }



        public MainViewModel()
        {
            _dispatcherTimer = new DispatcherTimer();
            _dispatcherTimer.Tick += DispatcherTimer_Tick;
            _dispatcherTimer.Interval = TimeSpan.FromSeconds(3);
            _dispatcherTimer.Start();
        }


        //I get every 3-4 sec from server new JSON data and I need update  with this data listbox in view
       private void DispatcherTimer_Tick(object sender, EventArgs eventArgs)
        {
            //server ping, call service method
            Account.Ping = _service.Ping(Account);

            //Refresh data in dictionary
            _freshUsers = _service.LoadUsers(Account);
            _users.Clear();
            SelectedUsersIndex = 1;

            foreach (var freshUser in _freshUsers)
            {
                _users.Add(freshUser);
            }

            //check if you have new messanges
            if (Account.Ping.Rp > 0)
            {
                //load new messanges
                for (int i = 0; i < Account.Ping.Rp; i++)
                {
                    #region load rp
                    try
                    {
                        Rp message = _service.LoadRp(Account);

                        if (message != null)
                        {
                            //show messages
                        }
                    }
                    catch (Exception exception)
                    {
                        if (exception.Message == "You haven&#8217;t any messanged")
                        {

                        }
                        throw exception;// how handle show this exception in view?
                    }
                    #endregion
                }
            }
        }
    }
4

1 回答 1

8

DispatcherTimer正在您的 UI 线程上运行,因此当它运行时您的检查您的 UI 可能会在DispatcherTimer_Tick消息运行时冻结。如果DispatcherTimer_Tick需要 2 秒才能运行,那么每 3 秒您将 UI 冻结 2 秒。用户不会喜欢这样。

所有服务调用都应该在非 UI 线程上完成,这样您就不会锁定 UI,所以我建议使用计时器并执行以下操作:

public MainViewModel() 
{ 
   _stTimer = new System.Threading.Timer(Timer_Tick,null,3000,3000); 
   _dispatcher = Dispatcher.CurrentDispatcher;
} 

private void Timer_Tick(object sender)
{
   Account.Ping = _service.Ping(Account); 
   //Refresh data in dictionary 
   _freshUsers = _service.LoadUsers(Account); 
   _users.Clear(); 
   SelectedUsersIndex = 1; 

   foreach (var freshUser in _freshUsers) 
   { 
      _users.Add(freshUser); 
   } 

   for(int i=0;i<Account.Ping.Rp; i++)
   {
       //check if you have new messanges 
       if (Account.Ping.Rp > 0) 
       { 
           Rp message = _service.LoadRp(Account); 
           _messages.Add(message);
       } 
    }

    _dispatcher.BeginInvoke((Action)(()=>{OnPropertyChanged("Messages");}));
}

在这里,我们使用系统计时器来检查不同线程上的更改,因此您的 UI 将不受任何处理的影响。当我们想要通知 UI 发生了变化时,我们可以使用 _dispatcher(我们在构造函数中创建的 UI 调度程序)在 UI 线程上“BeginInvoke”一个方法。

这将使您的应用程序看起来更快。一个好的经验法则是尽可能远离 Dispatcher 线程;仅在您使用 UI 做某事时使用它。所有其他处理都应该在后台线程上。

希望这可以帮助

于 2011-10-03T13:26:25.913 回答