我在WPF4.5 (.net 4.5)中有一个奇怪的行为。我使用关键字等待和异步来运行长操作(例如加载一个大的BitmapImage,图像控件的基础)。问题是服务员没有返回主UI线程,因为我得到了著名的例外:
调用线程无法访问此对象,因为其他线程拥有该对象。
有人能帮我吗?
这里我的代码:
按钮的事件处理程序:
private void GetExifData_Click(object sender, RoutedEventArgs e)
{
// Async method
(new AnalyzeSingleImage()).RunExif(this);
}main方法(在单独的类中,相同的程序集)
public async void RunExif(MainWindow win)
{
// here I run correctly code on the main UI Thread
..
..
// ASYNC !!!
BitmapImage bi = await LoadImageAsync(fileName);
Image img = new Image();
img.Source = bi; // *********** HERE I GET THE EXCEPTION *************
..
..
}异步方法:
private Task<BitmapImage> LoadImageAsync(string fileName)
{
return Task<BitmapImage>.Run(() => LoadImage(fileName));
}长时间法:
private BitmapImage LoadImage(string fileName)
{
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri(fileName);
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.EndInit();
return bi;
}有人能帮我吗?
发布于 2014-06-29 13:50:24
LoadImage在线程池上运行,因为您使用Task.Run将它推到了那里。在不同的线程上使用UI元素是有效的,但是您必须在同一个线程上一致地访问它们。
您创建的BitmapImage现在绑定到线程池线程。它不能与主UI相结合。
因此,最好的做法是在单个线程上只使用UI。在主线程上创建位图。
如果我还记得WPF正确的话,创建BitmapImage是非常快速的,而且加载图像也是异步的。
发布于 2014-07-16 11:26:08
最后,我使用了以下方法:
在主用户界面上
BitmapImage bi = await LoadImageAsync(fileName);
Image img = new Image();
img.Source = bi;
borderImg.Child = img;漫长的任务..。
private Task<BitmapImage> LoadImageAsync(string fileName)
{
return Task<BitmapImage>.Run(() => LoadImage(fileName));
}诀窍是使用冻结成员!!
private BitmapImage LoadImage(string fileName)
{
BitmapImage bi = new BitmapImage();
bi.BeginInit();
//bi.StreamSource = imgAsStream;
bi.UriSource = new Uri(fileName);
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.DecodePixelWidth = 400; // riduce l'utilizzo di memoria!
bi.EndInit();
bi.Freeze(); // IMPORTANTE, ALTRIMENTI RITORNANDO ALLA UI Thread ho un errore!!!!
return bi;
}https://stackoverflow.com/questions/24459055
复制相似问题