【问题标题】:BackgroundWorker vs NotifyPropertyChanged issueBackgroundWorker 与 NotifyPropertyChanged 问题
【发布时间】:2010-10-08 14:57:55
【问题描述】:

我有在 BackgroundWorker 中执行一些计算的 WPF 应用程序。问题是当我尝试在 RunWorkerCompleted 事件处理程序中更新属性(在 setter 中调用 NotifyPropertyChanged)时,我得到 InvalidOperationException - The calling thread cannot access this object because a different thread owns it.

This MSDN article 说 BackgroundWorker 自己处理线程同步,所以我不应该关心使用 Dispatcher。但我发现它没有正确处理 NotifyPropertyChanged。

谁能帮我解决这个问题?

编辑

这是我的代码(对一些不相关的功能感到抱歉):

backgroundWorker.DoWork += delegate(object sender, DoWorkEventArgs args)
                                           {
                                               var action = (Func<Bitmap>) args.Argument;
                                               args.Result = BitmapUtil.BitmapSourceFromBitmap(action());
                                           };

backgroundWorker.RunWorkerCompleted += delegate(object sender, RunWorkerCompletedEventArgs args)
                                                       {
                                                           if (args.Cancelled || (args.Error != null))
                                                           {
                                                               return;
                                                           }

                                                           ImageProcessed = (BitmapSource) args.Result;
                                                       };

...

public BitmapSource ImageProcessed
        {
            get { return imageProcessed; }

            set
            {
                imageProcessed = value;
                OnPropertyChanged(VMUtil.GetNameOf<ImageAnalyzerViewModel>(vm => vm.ImageProcessed));
            }
        }

【问题讨论】:

  • 请显示一些关于您如何设置属性的代码。文章有点误导,DoWork函数中的对象在另一个线程中,不能直接在线程外使用。

标签: wpf thread-safety backgroundworker


【解决方案1】:

问题不是由RunWorkerCompleted 中的任何代码引起的。该代码在创建BackgroundWorker 的同一线程上运行。问题出在实际在后台运行的方法中。

如果没有看到该代码,很难说这个问题可能是什么。您默默地丢弃该方法引发的任何错误,而不是记录或报告 args.Error 中的内容,这一事实也可能导致问题。

【讨论】:

  • 但是如果我评论更新属性的行 (ImageProcessed = (BitmapSource) args.Result;) 甚至 OnPropertyChanged 调用,一切正常。
  • 哦,呵呵。您正在后台线程上创建BitmapSource,它是DispatcherObject,因此具有线程亲和力。您可以通过在BitmapSource 上调用Freeze 来解决问题;如果没有,您可能必须在RunWorkerCompleted 中创建实际的BitmapSource 对象(这可能不是操作中运行缓慢的部分)。
  • 但是如果我不调用 OnPropertyChanged,你怎么解释一切正常?
  • 提高 PropertyChanged 使 UI 线程尝试访问该对象。
【解决方案2】:

这似乎是一个跨线程问题试试这个:

public BitmapSource ImageProcessed         
{             
    get
    { 
        return imageProcessed; 
    }              
    set         
    {                 
         imageProcessed = value;   
         // bring the following to the main thread
         Deployment.Current.Dispatcher.BeginInvoke(() =>
         {
            OnPropertyChanged(VMUtil.GetNameOf<ImageAnalyzerViewModel>(vm => vm.ImageProcessed));   
          }); 

  }         
} 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多