最近在做一个WPF的电子书程序,书页都保存为.jpg
格式。由于图片都是高质量的,程序在切换页面时会卡顿。
我试图在用户在另一个线程中看到的当前图像之后缓存一些图像。但它给了我一个错误。
An unhandled exception of type 'System.InvalidOperationException' occurred in WindowsBase.dll
Additional information: The calling thread cannot access this object because a different thread owns it.
我可以通过添加 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();
}
}
}
您必须卡住 BitmapImage 以使其可跨线程访问:
cachebmp = new BitmapImage(new Uri(file.FullName));
cachebmp.Freeze();
memcache.Set(id, cachebmp, policy);
也就是说,您的代码可以在很多方面进行改进。最好使用 ThreadPool
线程或 BackgroundWorker
或 Task
执行后台任务。
此外,如果图像文件不存在,您不应该使用 num = 0
递归调用 GetBitmap(num)
。如果 0.jpg
也丢失了会怎样?
我是一名优秀的程序员,十分优秀!