C# 图片被另一个进程使用(layoutpanel)
因此,我用图像填充浮动布局面板,代码如下:C# 图片被另一个进程使用(layoutpanel),c#,image,dispose,flowlayoutpanel,system.io.file,C#,Image,Dispose,Flowlayoutpanel,System.io.file,因此,我用图像填充浮动布局面板,代码如下: private void FillPanel(string sql) { panel.Controls.Clear(); SQLiteConnection dbConnect = new SQLiteConnection("Data Source=" + dbFullPath + ";Version=3;"); dbConnect.Open(); SQLiteComma
private void FillPanel(string sql)
{
panel.Controls.Clear();
SQLiteConnection dbConnect = new SQLiteConnection("Data Source=" + dbFullPath + ";Version=3;");
dbConnect.Open();
SQLiteCommand runQuery = new SQLiteCommand(sql, dbConnect);
SQLiteDataReader reader = runQuery.ExecuteReader();
while (reader.Read())
{
PictureBox pB = new PictureBox();
pB.Image = Image.FromFile(reader["imgPath"].ToString());
pB.Size = new Size(100, 100);
pB.SizeMode = PictureBoxSizeMode.StretchImage;
pB.Padding = new Padding();
pB.Margin = new Padding(5,5,5,5);
pB.Name = reader["name"].ToString();
toolTip_Main.SetToolTip(pB, pB.Name);
pB.DoubleClick += img_DoubleClick;
panel.Controls.Add(pB);
}
dbConnect.Close();
}
如果我稍后尝试删除源图片,我会收到一条错误消息
“image.png被另一个进程使用”
要删除图像,我使用以下代码:
private void Delete()
{
foreach (Control x in panel.Controls)
{
if (x is PictureBox)
{
PictureBox pb = x as PictureBox;
string name = pb.Name;
DirectoryInfo pF = new DirectoryInfo(pictureFolder);
foreach (FileInfo file in pF.GetFiles())
{
if(file.Name == name+".png")
{
pb.InitialImage = null;
pb.Dispose();
file.Delete();
break;
}
}
}
}
}
如果我没有用图像填充面板,我可以删除它们。
我只是不知道在'initialimage=null'&.dispose旁边我还能做些什么来清除面板中的图像
但他们似乎在某处鬼影
有什么想法吗?打开图像时要记住的基本规则如下:
- 从文件创建的
对象,在图像被释放之前防止文件被覆盖或删除图像
- 从流创建的
对象。与文件不同的是,没有任何活动强制执行此操作,但在关闭流后,图像在保存、克隆或以其他方式操作时会出现错误图像
Image.FromFile(字符串文件名)
实际上只是新位图(字符串文件名)
构造函数的包装器。我个人建议不要使用Image.FromFile
,因为它会丢失返回对象的更精确的位图类型。)
至于您的问题,处理图片盒
似乎不会处理实际图像。这可能可以通过先显式处理pb.Image
来解决:
Image img = pb.Image;
// Needs to happen in this order so the UI will never try to paint the disposed image
pb.Image = null;
if (img != null)
img.Dispose();
file.Delete();
break;
请注意,处理实际图像框可能会导致问题;您应该首先将其从其父控件中删除,以便它不再显示在UI上,否则您的窗体将开始抛出“object disposed”异常,因为它尝试绘制的某个控件无效
解决锁定问题的另一种方法是从磁盘读取位图,使用new bitmap(Image)
构造函数从中创建一个新位图,然后处理从文件初始化的位图对象。最好的方法是使用指令,如下所示:
using (Bitmap im = new Bitmap(reader["imgPath"].ToString()))
pB.Image = new Bitmap(im);
通常,您应该始终清理创建的图像对象。请注意,这实际上是在一个32bppARGB的新图像上绘制图像,从而丢失图像的任何原始格式。虽然在你的情况下,我想这并不重要,因为它只是为了显示在用户界面上。(注意,如果您确实需要完整的1:1图像数据克隆,而不需要指向流或文件的任何链接,则有多种方法可以做到这一点。)打开图像时要记住的基本规则如下:
- 从文件创建的
图像
对象,在图像被释放之前防止文件被覆盖或删除
- 从流创建的
图像
对象。与文件不同的是,没有任何活动强制执行此操作,但在关闭流后,图像在保存、克隆或以其他方式操作时会出现错误
(如果您想知道,Image.FromFile(字符串文件名)
实际上只是新位图(字符串文件名)
构造函数的包装器。我个人建议不要使用Image.FromFile
,因为它会丢失返回对象的更精确的位图类型。)
至于您的问题,处理图片盒
似乎不会处理实际图像。这可能可以通过先显式处理pb.Image
来解决:
Image img = pb.Image;
// Needs to happen in this order so the UI will never try to paint the disposed image
pb.Image = null;
if (img != null)
img.Dispose();
file.Delete();
break;
请注意,处理实际图像框可能会导致问题;您应该首先将其从其父控件中删除,以便它不再显示在UI上,否则您的窗体将开始抛出“object disposed”异常,因为它尝试绘制的某个控件无效
解决锁定问题的另一种方法是从磁盘读取位图,使用new bitmap(Image)
构造函数从中创建一个新位图,然后处理从文件初始化的位图对象。最好的方法是使用指令,如下所示:
using (Bitmap im = new Bitmap(reader["imgPath"].ToString()))
pB.Image = new Bitmap(im);
通常,您应该始终清理创建的图像对象。请注意,这实际上是在一个32bppARGB的新图像上绘制图像,从而丢失图像的任何原始格式。虽然在你的情况下,我想这并不重要,因为它只是为了显示在用户界面上。(注意,如果您确实需要一个完整的1:1图像数据克隆,而不需要指向流或文件的任何链接,可以通过多种方法来实现,但是。)