WPF和线程编组

时间:2012-04-06 21:42:18

标签: wpf multithreading windows-phone-7

道歉,如果我只是没有弄清楚实际的方法,但我已经浏览了各种博客文章,并且感觉不到任何接近答案。

我正在编写一个WP7应用程序,它本质上是一个具有时间转换成本的秒表。

模型包含方法Start()和Pause()以及double属性Cost。在ViewModel中,我使用ICommands for Start()和Pause()来触发底层模型函数。但是在调用Start()之后,我希望UI能够反映不断增加的成本。

我考虑了几种方法:

  1. ViewModel通过自我实现的订阅者订阅Model 模型和模型在模型运行时每隔几毫秒通知所有订户。
  2. View Model StartCommand启动一个后台工作程序,每隔几毫秒在Cost属性上触发一个RaisePropertyChanged事件。
  3. 我选择了第二个提案,因为模型根本不需要线程(它只记录用户按下开始和暂停的时间并在成本计算中使用它)。我的方法基于http://msdn.microsoft.com/en-us/library/cc221403(VS.95).aspx

    但是当我尝试运行它时,我收到“UnauthorizedAccessException”。代码如下:

    Backgroundworker在构造函数

    中创建为VM成员
    public MeetingCostViewModel()
    {
        _backgroundWorker = new BackgroundWorker
        {
            WorkerSupportsCancellation = true,
            WorkerReportsProgress = false,
        };
        _backgroundWorker.DoWork += DoWork;
    }
    

    StartCommand触发后台工作程序运行

    private DelegateCommand _startCommand;
        public ICommand StartCommand
        {
            get
            {
                return _startCommand ?? (_startCommand = new DelegateCommand(
                    delegate
                    {
                        _meetingCost.Start();
                        _keepUpdating = true;
                        if (_backgroundWorker.IsBusy != true)
                        {
                            _backgroundWorker.RunWorkerAsync();
                        }
                    }));
            }
        }
    

    这是基于http://blog.lab49.com/archives/1166

    的实际工作方法
    private void DoWork(object sender, DoWorkEventArgs e)
    {
        while (true)
        {
            PropertyChangedEventHandler temp = PropertyChanged;
            if (temp != null)
            {
                temp(this, new PropertyChangedEventArgs("Cost"));
            }
            Thread.Sleep(50);
        }
    }
    

    我不确定这是否是正确的方法,但我想保留View数据绑定并且没有'代码隐藏',但是这里的大多数替代响应都需要明确设置控件,我想以任何明智的代价避免它。

2 个答案:

答案 0 :(得分:1)

可能是,UnauthorizedAccessException意味着您正在从其他线程访问UI对象。你的事件处理程序在错误的线程上触发。

更改代码以使用将在UI线程上触发的DispatcherTimer。

答案 1 :(得分:0)

另一种解决方案是在BackgroundWorker的报告进度事件处理程序中进行更新。它将自动编组到正确的线程。