2010-09-13 54 views
2

在我正在编写的WPF应用程序中,我有一个TransformedBitmap属性,它绑定到UI上的Image对象。每当我改变这个属性时,图像被更新(并且因此正在被显示到屏幕上的图像被更新)。为了防止结冰或不响应,而我检索下一个图像的UI,我试图快照检索,像这样一个BackgroundWorker:从BackgroundWorker线程更新图像UI属性

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

然后,在我的RunWorkerCompleted方法,我有以下:

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

这似乎是工作好,直到用来告诉Image对象的NotifyPropertyChanged方法来更新,当我更新CurrentImage财产;我得到一个交叉线程错误。

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));  
    } 
} 

我真的不知道如何改变事情或做些什么不同来解决这个错误。在过去的几个小时里,我一直在阅读关于BackgroundWorkers的内容,在我看来,我应该能够在RunWorkerCompleted方法中设置好CurrentImage;至少从我能说的来看。任何帮助,将不胜感激!谢谢!

+0

查看我的答案更新。我已经处理了这个问题,它的工作原理。 – 2010-09-13 20:41:56

回答

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

这应该工作...

更新

在你的情况,你正在使用冻结的对象,问题是在你已经创建需要在发送之前被冻结的位图它在UI线程中。因此,您的DoWork将如下所示:

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

然后在RunWorkerCompleted中更新了我上面写的属性。

+0

这也导致“异常已被调用的目标抛出”,而异常仍然包含相同的跨线程错误。 – JToland 2010-09-13 19:40:45

+0

这现在完美了!谢谢你! – JToland 2010-09-14 11:45:51

+0

不客气! – 2010-09-14 12:12:03

2

的控制(图)只能在创建它的线程进行更改。所以基本上会发生什么是你的后台线程改变你的对象的属性,然后触发PropertyChanged事件,然后由WPF使用它,然后尝试修改Image控件(记住我们仍然在BackgroundThread贯穿此链的事件)。

幸运的是,解决方法是非常简单的:

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

您需要将您的窗口或控件的引用这个工作,但是这基本上是排队委托给UI线程上运行,而不是后台线程。

+0

这实际上导致了“调用目标引发的异常”错误... – JToland 2010-09-13 19:29:10

+0

这可能是因为它被WPF包裹在某处,但我猜想一个InnerException将包含跨线程违例异常。 – CodingGorilla 2010-09-13 19:32:41

+0

Dispatcher.Invoke()不起作用? – CodingGorilla 2010-09-13 19:46:16