2010-09-13 55 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