2017-03-03 119 views
0

我有一個簡單的方法調用返回bitmap圖像的函數。無法從WPF中的其他線程更新UI

private void ImageToGrayScale(object sender, RoutedEventArgs e) 
{ 
    pbStatus.Visibility = Visibility.Visible; 
    if (loadedImage != null) 
    { 
     new Thread(() => 
     { 
      BitmapImage bitmapImage= ThreadProcedure(); 
      this.Dispatcher.Invoke(new Action(()=> { 
       pbStatus.Visibility = Visibility.Hidden; 
       EditedImage.Source = bitmapImage; 
      })); 
     }).Start(); 
    } 
    else 
    { 
     MessageBox.Show("Please select the image first!"); 
    } 
} 

每次在一行:EditedImage.Source = bitmapImage;一個得到一個錯誤:

The calling thread cannot access this object because a different thread owns it.

另外,這裏是它返回一個bitmap圖像的方法。

private BitmapImage ThreadProcedure() 
{ 
    Bitmap editedImage = new Bitmap(loadedImage); 
    for (int x = 0; x < editedImage.Width; x++) 
    { 
     for (int y = 0; y < editedImage.Height; y++) 
     { 
      Color pixelColor = editedImage.GetPixel(x, y); 
      int rgb = (int)((pixelColor.R + pixelColor.G + pixelColor.B)/3); 
      editedImage.SetPixel(x, y, Color.FromArgb(rgb, rgb, rgb)); // Now greyscale 
     } 
    } 
    return Converter.ConvertBitmapToBitmapImage(editedImage, extension); 
} 
+0

什麼是loadedImage,是這個問題嗎?您可以在線程過程中從中創建新的位圖。或者,您可能應該將bitmapImage作爲參數傳遞給調度程序委託... – japesu

+0

此處的問題很可能與'bitmapImage'對象有關 - 它是在與Dispatcher同步上下文不同的線程上創建的。因此,從它讀取,並將其複製到源可能會因此錯誤而失敗。爲了測試這個,將調用移動到調度程序調用中的'ThreadProcedure'並查看它是否工作。 – Baldrick

+0

@Baldrick,它的工作原理,但它阻止了UI線程和它沒有響應的窗口。 –

回答

1

你應該凍結BitmapImage通過調用其Freeze()方法,以便能夠使用它在另一個線程比它創建一個:

new Thread(() => 
{ 
     BitmapImage bitmapImage = ThreadProcedure(); 
     bitmapImage.Freeze(); //<-- 

     this.Dispatcher.Invoke(new Action(() => { 
      pbStatus.Visibility = Visibility.Hidden; 
      EditedImage.Source = bitmapImage; 
     })); 
}).Start(); 
+0

是的,它的工作!非常感謝 !。 –

-1

用於創建更新映像線程沒有做使用Dispatcher.BeginInvoke代替,這將執行的操作異步的最好的事情。

"Control.BeginInvoke: Executes on the UI thread, and calling thread doesn't wait for completion."

刪除線程部分並使用此代碼應該解決問題。

  BitmapImage bitmapImage= ThreadProcedure(); 

     Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() => 
     { 
      pbStatus.Visibility = Visibility.Hidden; 
      EditedImage.Source = bitmapImage; 
     })); 
+0

我得到了同樣的錯誤。 –