简体   繁体   English

无法从WPF中的另一个线程更新UI

[英]Cannot update UI from another thread in WPF

I have a simple method which call a function that returns a bitmap image. 我有一个简单的方法,该方法调用一个返回bitmap图像的函数。

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

Everytime at line: EditedImage.Source = bitmapImage; 每次在线: EditedImage.Source = bitmapImage; a get an error: 得到一个错误:

The calling thread cannot access this object because a different thread owns it. 调用线程无法访问该对象,因为其他线程拥有它。

Also, here is the method which returns a bitmap image. 另外,这是返回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);
 }

You should freeze the BitmapImage by calling its Freeze() method in order to be able to use it on another thread than the one on which it was created: 您应该通过调用Freeze()方法冻结BitmapImage ,以便能够在创建该线程的线程之外的另一个线程上使用它:

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

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

There is a difference between Dispatcher and Application.Current.Dispatcher : DispatcherApplication.Current.Dispatcher之间有一个区别:

Dispatcher.CurrentDispatcher vs. Application.Current.Dispatcher Dispatcher.CurrentDispatcher与Application.Current.Dispatcher

Make sure the dispatcher you use is the same one for the EditedImage object. 确保您使用的调度程序与EditedImage对象相同。 You could use the latter dispatcher directly (see https://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcherobject.dispatcher(v=vs.110).aspx ) 您可以直接使用后一个调度程序(请参阅https://msdn.microsoft.com/zh-cn/library/system.windows.threading.dispatcherobject.dispatcher(v=vs.110).aspx

Creating a thread for updating an image is not the best thing to do use Dispatcher.BeginInvoke instead this will execute the action asynchronous. 创建用于更新图像的线程不是使用Dispatcher.BeginInvoke的最佳方法,而是将异步执行操作。

"Control.BeginInvoke: Executes on the UI thread, and calling thread doesn't wait for completion." “ Control.BeginInvoke:在UI线程上执行,并且调用线程不等待完成。

Remove the thread part and use this code the problem should be solved. 删除线程部分,并使用此代码应解决的问题。

         BitmapImage bitmapImage= ThreadProcedure();

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

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

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