我试图在不同的线程中加载图像,但图像永远不会更新。
public class MyImage : System.Windows.Controls.Image
{
public MyImage()
{
this.Loaded += new RoutedEventHandler(MyImage_Loaded);
}
void MyImage_Loaded(object sender, RoutedEventArgs e)
{
//mypath=@"c:\test.jpg";
var t = Task<ImageSource>.Factory.StartNew(() => GetImage(mypath));
Source = t.Result;
}
以下作品,但它是UI线程:
Source = GetImage(mypath);
我尝试使用BackgroundWorker,但结果是一样的。 没有MVVM可以这样做吗?
答案 0 :(得分:3)
因为您在不同的线程上创建了ImageSource
,所以您要在其上使用它
调用线程无法访问此对象,因为另一个线程拥有它
例外并解决您的问题,请致电ImageSource
上的Freeze()
。但是,即使您在不同的线程上加载图像,您的代码也会阻止UI线程,直到它准备就绪:
var t = Task<ImageSource>.Factory.StartNew(() => GetImage(mypath));
Source = t.Result; //this line blocks UI thread until Result is ready
如果您想避免将其更改为:
Task.Factory.StartNew(() =>
{
var source = GetImage(mypath);
source.Freeze();
this.Dispatcher.Invoke(() => this.Source = source);
});
这应该在不同的线程上加载图像并在它准备就绪时更新Source
而不阻塞UI线程
答案 1 :(得分:0)
尝试从GetImage(或从其结果)返回byte []或流,然后使用Dispatcher.Invoke
调用UI线程上的帮助程序,该线程从byte []或流重新更新图像并更新MyImage的来源。
这是我工作的POC。您想检查它以正确处理流等。
(注意:disp
是“发布”到UI的调度程序
Task.Factory.StartNew(() =>
{
var result = GetImage();
var bitmap = new BitmapImage();
var stream = result;
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.StreamSource = stream;
bitmap.EndInit();
bitmap.Freeze();
stream.Dispose();
disp.Invoke(new Action(()=> MyImage.Source = bitmap));
});
GetImage()
:
private MemoryStream GetImage()
{
System.Threading.Thread.Sleep(35000);
var filePath = @"C:\temp\2013-01-08-235341.jpg";
MemoryStream memoryStream = null;
if (File.Exists(filePath))
{
memoryStream = new MemoryStream();
byte[] fileBytes = File.ReadAllBytes(filePath);
memoryStream.Write(fileBytes, 0, fileBytes.Length);
memoryStream.Position = 0;
}
return memoryStream;
}