You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

删除已加入ImageList和ListView的图片文件时提示文件被占用问题

问题与解决方案

问题描述

加载文件夹内图片到ImageList,绑定ListView显示缩略图;点击ListView项时在PictureBox展示原图。执行删除操作时,已将PictureBox的Image和ImageLocation设为null,移除ListView与ImageList中的对应项,但调用File.Delete(path)时触发错误:

The process cannot access the file "path to image file" because it is being used by another process

现有代码

加载图片代码

private void LoadImages(string path)
{
    try
    {
        imageList = new ImageList() { ColorDepth = ColorDepth.Depth32Bit, ImageSize = new Size(194, 194), TransparentColor = Color.Transparent };
        listView.LargeImageList = imageList;

        IEnumerable<string> files = Directory.EnumerateFiles(path, "*.*", SearchOption.TopDirectoryOnly);         

        foreach (string file in files)
        {
                AddImage(file);
        }
        if (listView.Items.Count > 0)
        {
            string firstImage = listView.Items[0].ImageKey;
            selectedPicBox.Image = Image.FromFile(firstImage);
            selectedPicBox.ImageLocation = firstImage;
        }
    }
    catch (Exception ex)
    {
        Program.EventLog.WriteEntry($"Scan-Loading scans : {ex}", EventLogEntryType.Error, 101);
        throw;
    }
}

添加图片代码

imageList.Images.Add(path, Image.FromStream(new MemoryStream(File.ReadAllBytes(path)), true, false));
listView.Items.Add(path, file.Name, path);  

删除图片代码

string path = listView.SelectedItems[0].ImageKey;
selectedPicBox.Image = null;
selectedPicBox.ImageLocation = null;

listView.SelectedItems.Clear();
listView.Items.RemoveByKey(path);

imageList.Images[path].Dispose();
imageList.Images.RemoveByKey(path);

File.Delete(path);

问题根源

  1. Image.FromFile锁定文件:加载第一张图时使用Image.FromFile,该方法会保持文件句柄直到Image对象被Dispose,仅将selectedPicBox.Image设为null不会释放句柄。
  2. Image资源释放不彻底:删除时虽调用了imageList.Images[path].Dispose(),但未确保所有关联的Image引用都被清理,且ImageList内部可能仍持有资源。
  3. 流资源管理缺失:添加图片时创建的MemoryStream未被正确管理,可能导致底层资源未及时释放。

修复方案

1. 修改图片加载逻辑,避免文件锁定

替换Image.FromFile为内存流加载,避免锁定文件:

if (listView.Items.Count > 0)
{
    string firstImage = listView.Items[0].ImageKey;
    using (var ms = new MemoryStream(File.ReadAllBytes(firstImage)))
    {
        selectedPicBox.Image = Image.FromStream(ms, true, false);
    }
    // 移除ImageLocation设置,避免额外的文件引用
    // selectedPicBox.ImageLocation = firstImage;
}

2. 完善删除逻辑,确保资源完全释放

删除时先Dispose所有关联的Image对象,再清理控件项,最后执行文件删除:

string path = listView.SelectedItems[0].ImageKey;

// 先释放PictureBox中的Image资源
selectedPicBox.Image?.Dispose();
selectedPicBox.Image = null;
selectedPicBox.ImageLocation = null;

// 移除ListView选中项
var selectedItem = listView.SelectedItems[0];
listView.Items.Remove(selectedItem);

// 释放并移除ImageList中的对应图片
if (imageList.Images.ContainsKey(path))
{
    var targetImage = imageList.Images[path];
    targetImage.Dispose();
    imageList.Images.RemoveByKey(path);
}

// 强制触发垃圾回收,加快资源释放
GC.Collect();
GC.WaitForPendingFinalizers();

// 执行文件删除
File.Delete(path);

3. 优化AddImage方法,规范流资源管理

显式管理文件流与内存流的生命周期,确保资源被正确回收:

private void AddImage(string path)
{
    using (var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read))
    using (var memoryStream = new MemoryStream())
    {
        fileStream.CopyTo(memoryStream);
        memoryStream.Position = 0;
        var image = Image.FromStream(memoryStream, true, false);
        imageList.Images.Add(path, image);
    }
    var fileInfo = new FileInfo(path);
    listView.Items.Add(path, fileInfo.Name, path);
}

4. 确保ImageList的重复初始化安全

若LoadImages可能被多次调用,先释放旧ImageList的所有资源:

private void LoadImages(string path)
{
    try
    {
        // 释放旧ImageList资源
        if (imageList != null)
        {
            foreach (Image img in imageList.Images)
            {
                img.Dispose();
            }
            imageList.Dispose();
        }

        imageList = new ImageList() { ColorDepth = ColorDepth.Depth32Bit, ImageSize = new Size(194, 194), TransparentColor = Color.Transparent };
        listView.LargeImageList = imageList;

        IEnumerable<string> files = Directory.EnumerateFiles(path, "*.*", SearchOption.TopDirectoryOnly);         

        foreach (string file in files)
        {
            AddImage(file);
        }

        if (listView.Items.Count > 0)
        {
            string firstImage = listView.Items[0].ImageKey;
            using (var ms = new MemoryStream(File.ReadAllBytes(firstImage)))
            {
                selectedPicBox.Image = Image.FromStream(ms, true, false);
            }
        }
    }
    catch (Exception ex)
    {
        Program.EventLog.WriteEntry($"Scan-Loading scans : {ex}", EventLogEntryType.Error, 101);
        throw;
    }
}

内容的提问来源于stack exchange,提问作者Mehdi Foroughi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 07:32:17