我最近在WPF工作电子书程序,本书的页面都保存为.jpg
格式。由于图像都是高质量的,因此程序在切换页面时会滞后。
我试图在用户在另一个线程中看到的当前图像之后缓存一些图像。但它给了我一个错误。
未处理的类型' System.InvalidOperationException'发生在WindowsBase.dll
中附加信息:调用线程无法访问此对象,因为另一个线程拥有它。
我可以通过添加Invoke
来修复错误,但性能就像没有内存缓存一样。
但是没有Invoke
,程序会显示上面的错误。而且我不知道如何解决它。
我试着让代码变得尽可能简单。
感谢任何帮助。
完整代码:
using System;
using System.Collections.Specialized;
using System.IO;
using System.Runtime.Caching;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;
namespace ThreadedMemoryCache_Test
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
MemoryCache memcache;
int num = 0;
Image img;
int BufferPages = 2;
public MainWindow()
{
InitializeComponent();
//Change Content
img = new Image();
Content = img;
//Mouse Events
MouseDown += (s, e) =>
{
int add = 0;
if (e.LeftButton == MouseButtonState.Pressed)
add--;
else if (e.RightButton == MouseButtonState.Pressed)
add++;
else
return;
num += add;
img.Source = GetBitmap(num); //Error here
Buffer();
};
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//Initiallize MemoryCache
NameValueCollection CacheSettings = new NameValueCollection(3);
CacheSettings.Add("CacheMemoryLimitMegabytes", Convert.ToString(1));
CacheSettings.Add("physicalMemoryLimitPercentage", Convert.ToString(10));
CacheSettings.Add("pollingInterval", Convert.ToString("00:00:10"));
memcache = new MemoryCache("BitmapCache", CacheSettings);
//Get First Photo
img.Source = GetBitmap(num);
Buffer();
}
BitmapImage GetBitmap(int num)
{
String id = num.ToString();
BitmapImage cachebmp = memcache[id] as BitmapImage;
if (cachebmp == null)
{
CacheItemPolicy policy = new CacheItemPolicy();
String name = num.ToString() + ".jpg";
FileInfo file = new FileInfo(name);
if(!file.Exists)
{
num = 0;
return GetBitmap(num);
}
cachebmp = new BitmapImage(new Uri(file.FullName));
memcache.Set(id, cachebmp, policy);
}
return cachebmp;
}
void Buffer()
{
//Start Thread
Thread cachethread = new Thread(() =>
{
for (int i = 1; i <= BufferPages; i++)
{
//Adding invoke fixes the error, but it seems to delay the main thread and cause lag.
//this.Dispatcher.Invoke((Action)(() =>
//{
GetBitmap(num + i);
//}));
}
});
cachethread.IsBackground = true;
cachethread.Start();
}
}
}
答案 0 :(得分:3)
您必须冻结BitmapImage以使其可跨线程访问:
cachebmp = new BitmapImage(new Uri(file.FullName));
cachebmp.Freeze();
memcache.Set(id, cachebmp, policy);
也就是说,您的代码可以通过多种方式得到改进。最好使用ThreadPool
主题或BackgroundWorker
或Task
来执行后台任务。
除此之外,如果图片文件不存在,您不应该使用GetBitmap(num)
递归num = 0
。如果0.jpg
也缺失会怎样?
答案 1 :(得分:0)
您应该使用BackgroundWorker
类。
在MainThread中启动时加载一些初始图像,然后为其余图像启动BackgroundWorker
。
有用的链接:How to: Use a Background Worker,BackgroundWorker In Wpf。