我想要一个监视ceratain文件夹并显示该文件夹中出现的新图像的应用程序。我成功设法使用FileSystemWatcher
类检测新图像,但是我有问题要显示它们。我有以下代码:
public partial class MainWindow : Window
{
FileSystemWatcher watcher = new FileSystemWatcher();
public MainWindow()
{
InitializeComponent();
watcher.Path = "C:/Users/maciejt/Pictures";
watcher.Filter = "*.jpg";
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
watcher.Created += new FileSystemEventHandler(OnCreated);
watcher.EnableRaisingEvents = true;
}
private void OnCreated(object source, FileSystemEventArgs e)
{
Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
image.Dispatcher.Invoke(new Action(() => { image.Source = new BitmapImage(new Uri(e.FullPath)); }));
}
}
适用于大约10-20个小(~100kB)图像和1-2个大(~4MB)的图像。稍后它会引发一个异常,即图像被另一个进程使用。我还在调试器中观察到,应用程序使用的内存随着每个新图像的增加而急剧增加,就像以前的图像没有被丢弃一样。
创建BitmapImage
并在Image
控件中显示它的正确方法是什么?
编辑:
我尝试了一个可能重复的建议解决方案,但是这仍然给了我相同的例外,这次甚至没有工作过。修改后的代码下方:
private void OnCreated(object source, FileSystemEventArgs e)
{
Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
image.Dispatcher.Invoke(new Action(() => { image.Source = LoadBitmapImage(e.FullPath); }));
}
public static BitmapImage LoadBitmapImage(string fileName)
{
using (var stream = new FileStream(fileName, FileMode.Open))
{
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = stream;
bitmapImage.EndInit();
bitmapImage.Freeze();
return bitmapImage;
}
}
答案 0 :(得分:0)
我设法找到了一个有效的解决方案:
private void OnCreated(object source, FileSystemEventArgs e)
{
Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
image.Dispatcher.Invoke(new Action(() => { image.Source = LoadBitmapImage(e.FullPath); }));
}
public static BitmapImage LoadBitmapImage(string fileName)
{
while (!IsFileReady(fileName))
{
Thread.Sleep(100);
}
using (var stream = new FileStream(fileName, FileMode.Open))
{
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = stream;
bitmapImage.EndInit();
bitmapImage.Freeze();
return bitmapImage;
}
}
public static bool IsFileReady(String sFilename)
{
// If the file can be opened for exclusive access it means that the file
// is no longer locked by another process.
try
{
using (FileStream inputStream = File.Open(sFilename, FileMode.Open, FileAccess.Read, FileShare.None))
{
return (inputStream.Length > 0);
}
}
catch (Exception)
{
return false;
}
}
我的猜测是FileSystemWatcher
在检查任何修改时暂时拥有该文件的所有权。等待一段时间后,文件解锁并准备好安全处理。不过,如果有人有更深入的解释或更好的解决方案,我很乐意看到它。
答案 1 :(得分:0)
您可能会遇到此问题,因为您没有处理已创建的位图对象。试试以下解决方案这将在创建新位图时处理您之前的位图。
BitmapImage _image;
private void OnCreated(object source, FileSystemEventArgs e)
{
if (_image != null)
{
FreeMemoryAcquiredByImage(_image);
_image = null;
}
_image = new BitmapImage(new Uri(e.FullPath));
//You may have to freeze _image here.
image.Dispatcher.Invoke(new Action(() => { image.Source = _image; }));
}