[英]Cannot update UI from another thread in WPF
我有一个简单的方法,该方法调用一个返回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!");
}
}
每次在线: EditedImage.Source = bitmapImage;
得到一个错误:
调用线程无法访问该对象,因为其他线程拥有它。
另外,这是返回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);
}
您应该通过调用Freeze()
方法冻结BitmapImage
,以便能够在创建该线程的线程之外的另一个线程上使用它:
new Thread(() =>
{
BitmapImage bitmapImage = ThreadProcedure();
bitmapImage.Freeze(); //<--
this.Dispatcher.Invoke(new Action(() => {
pbStatus.Visibility = Visibility.Hidden;
EditedImage.Source = bitmapImage;
}));
}).Start();
Dispatcher
和Application.Current.Dispatcher
之间有一个区别:
确保您使用的调度程序与EditedImage
对象相同。 您可以直接使用后一个调度程序(请参阅https://msdn.microsoft.com/zh-cn/library/system.windows.threading.dispatcherobject.dispatcher(v=vs.110).aspx )
创建用于更新图像的线程不是使用Dispatcher.BeginInvoke
的最佳方法,而是将异步执行操作。
“ Control.BeginInvoke:在UI线程上执行,并且调用线程不等待完成。
删除线程部分,并使用此代码应解决的问题。
BitmapImage bitmapImage= ThreadProcedure();
Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() =>
{
pbStatus.Visibility = Visibility.Hidden;
EditedImage.Source = bitmapImage;
}));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.