简体   繁体   English

从BackgroundWorker线程更新Image UI属性

[英]Updating an Image UI property from a BackgroundWorker thread

In a WPF application I'm writing, I have a TransformedBitmap property which is bound to an Image object on the UI. 在我正在编写的WPF应用程序中,我具有一个TransformedBitmap属性,该属性绑定到UI上的Image对象。 Whenever I change this property, the Image is updated (and thus the image being displayed to the screen is updated). 每当我更改此属性时,图像都会更新(因此,显示在屏幕上的图像也会更新)。 In order to prevent the UI from freezing or becoming unresponsive whilst I retrieve the next image, I'm attempting to the snapshot retrieval with a BackgroundWorker like this: 为了防止在检索下一个图像时UI冻结或变得无响应,我尝试使用BackgroundWorker进行快照检索,如下所示:

private void bw_DoWork(object sender, DoWorkEventArgs e)
{
  e.Result = this.snapshotHelper.GetSnapshot(ImageFormat.Bmp);
}

then, in my RunWorkerCompleted method, I have the following: 然后,在我的RunWorkerCompleted方法中,我有以下内容:

private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
  this.CurrentImage = (TransformedBitmap)e.Result;
  ....
}

This seems to work okay until on the NotifyPropertyChanged method used to tell the Image object to update when I update the CurrentImage property; 直到在更新CurrentImage属性时用于通知Image对象更新的NotifyPropertyChanged方法上,这似乎都可以正常工作。 I get a cross-thread error. 我收到跨线程错误。

public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
  if (PropertyChanged != null)
  {
  //The following causes a "the calling thread cannot access this object because a different thread owns it" error!
    PropertyChanged(this, new PropertyChangedEventArgs(info));      
  }
}

I really don't know how to change things around or what to do differently to get around this error. 我真的不知道该如何更改事物或采取其他措施来解决此错误。 I've been reading about BackgroundWorkers for the past couple of hours and it seems to me that I should be able to set CurrentImage fine in the RunWorkerCompleted method; 在过去的几个小时中,我一直在阅读有关BackgroundWorkers的信息,在我看来,我应该能够在RunWorkerCompleted方法中很好地设置CurrentImage。 at least from what I can tell. 至少根据我的判断。 Any help on this would be greatly appreciated! 任何帮助,将不胜感激! Thanks! 谢谢!

A control (Image) can only be changed on the Thread which created it. 控件(图像)只能在创建它的线程上更改。 So essentially what happens is your background thread changes the property on your object, which in turn fires the PropertyChanged event, which is then consumed by WPF, which then attempts to modify the Image control (remember we're still on the BackgroundThread throughout this chain of events). 因此,本质上发生的事情是您的后台线程更改了对象上的属性,这又触发了PropertyChanged事件,然后由WPF消耗该事件,然后WPF尝试修改Image控件(请记住,在整个链中,我们仍然在BackgroundThread上事件)。

Luckily, the fix is pretty simple: 幸运的是,修复非常简单:

private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
  myWindow.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(delegate() 
     {
        this.CurrentImage = (TransformedBitmap)e.Result;
        ....
     });
}

You will need a reference to your Window or Control for this to work, but this essentially queues up the delegate to run on the UI thread instead of the background thread. 您需要对Window或Control的引用才能使其正常工作,但这实际上使委托排队在UI线程而不是后台线程上运行。

Dispatcher.Invoke((Action<TransformedBitmap>) (obj => this.CurrentImage = obj), e.Result as TransformedBitmap);

This should work... 这应该工作...

Update 更新

In your case you are using freezable object, and the problem is in the bitmap that you have created need to be freezed before sending it in UI thread. 在您的情况下,您使用的是可冻结对象,问题在于您创建的位图需要先冻结,然后才能在UI线程中发送它。 So you DoWork will be as follows: 因此,您的DoWork将如下所示:

void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            var bmp = snapshotHelper.GetSnapshot(ImageFormat.Bmp);
            bmp.Freeze();
            e.Result = bmp;            
        }

Then in RunWorkerCompleted you update the property as I wrote above. 然后在RunWorkerCompleted中,按照我上面的描述更新属性。

Only dispatcher is allowed to interact with the UI. 只允许调度程序与UI交互。 Have a look here: 在这里看看:

http://www.jeff.wilcox.name/2010/04/propertychangedbase-crossthread/ http://www.jeff.wilcox.name/2010/04/propertychangedbase-crossthread/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM