2010-06-05 65 views
12

首先,我需要說我很喜歡WPF和C#。 應用程序:創建曼德爾布羅圖片(GUI) 我分派工作完全此這種情況下:WPF Dispatcher {「調用線程不能訪問這個對象,因爲一個不同的線程擁有它。」}

private void progressBarRefresh(){ 

     while ((con.Progress) < 99) 
     { 
      progressBar1.Dispatcher.Invoke(DispatcherPriority.Send, new Action(delegate 
       { 
        progressBar1.Value = con.Progress; 
       } 
      )); 
     } 
    } 

我得到的消息(標題)特林當與下面的代碼來做到這一點:

bmp = BitmapSource.Create(width, height, 96, 96, pf, null, rawImage, stride); 

this.Dispatcher.Invoke(DispatcherPriority.Send, new Action(delegate 
      {      
       img.Source = bmp; 
       ViewBox.Child = img; //vllt am schluss 
      } 
     )); 

我將嘗試解釋我的程序如何工作。 我創建了一個新的線程(因爲GUI不響應)來計算像素和顏色。在這個線程(方法)中,在計算準備就緒後,我使用Dispatcher刷新ViewBox中的圖像。

當我不把計算放在單獨的線程中時,我可以刷新或構建我的圖像。

回答

2

您正在您的worker(?)線程上創建位圖(bmp),然後將它傳遞給UI線程 - 這是失敗的。

您需要在UI線程上創建圖像。您可能需要某種方法來引用您想要顯示的圖像,並將信息傳遞給UI。

+1

您不需要在UI線程上創建圖像。你不能從一個線程在另一個線程上使用它(而.NET假定除非你將它標記爲* freeze *,否則它將被再次修改)。 – 2010-06-06 02:18:33

2

你也可以使用一個排隊機制在線程之間傳遞消息。畢竟,這就是Windows架構的工作原理。這就是調度員正在做的事情。您正將一個引用傳遞給該委託,該委託不屬於WPF線程。

所以,是的,你有基本的想法,但實際上你需要使用Action<T>(T object)傳位給其他線程,或在您的情況:

Dispatcher.Invoke(DispatcherPriority.Send, new Action<Bitmap>(delegate(Bitmap img) { 
    do things here... 
}), bmp); 
+1

不會有所作爲,您仍然共享被引用的對象。 – 2010-06-06 02:19:19

22

萬一你希望對象是在不同線程之間共享,然後總是在UI線程上創建該對象。稍後,當您想要訪問該對象時,可以檢查是否有權訪問該對象。如果您沒有訪問權限,請通過UI線程訪問重新調用該函數。下面的示例代碼:

private void YourMethod() 
    { 
     if (Application.Current.Dispatcher.CheckAccess()) 
     { 
      // do whatever you want to do with shared object. 
     } 
     else 
     { 
      //Other wise re-invoke the method with UI thread access 
      Application.Current.Dispatcher.Invoke(new System.Action(() => YourMethod())); 
     } 
    } 
2

當你得到一個Dispatcher你會得到一個不同的每一個不同的線程。

this.Dispatcher可能會給你另一個Dispatcher而不是UI,所以你會得到那個錯誤。

嘗試使用Application.Current.Dispatcher代替,這將始終返回UI線程的分派器。

如果您從其他線程使用Dispatcher.CurrentDispatcher,則可能會發生同樣的錯誤。

相關問題