图片被另一个进程使用(layoutpanel)
picture is used by another process (layoutpanel)
所以我用图像填充浮动布局面板,代码如下:
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 is used by another process"
要删除图像,我使用以下代码:
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 旁边我还能做些什么来摆脱面板内的图像。
但他们似乎在某个地方出现了鬼影。
对此有什么想法吗?
打开图像时要记住的基本规则如下:
- 从文件 will lock the file during the life cycle of the image object 创建的
Image
对象,防止文件被覆盖或删除,直到图像被释放。
- 从流 will need the stream to remain open for the entire life cycle of the image object 创建的
Image
对象。与文件不同,没有任何主动强制执行这一点,但在流关闭后,图像在保存、克隆或以其他方式操作时会出错。
(如果你想知道,Image.FromFile(String filename)
实际上只是 new Bitmap(String filename)
构造函数的包装器。我个人建议不要使用 Image.FromFile
,因为它失去了更精确的 Bitmap
返回对象的类型。)
至于你的问题,似乎处理 PictureBox
并没有处理实际图像。这可能可以通过首先显式处理 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 image)
构造函数从中创建一个新位图,然后处理从文件初始化的位图对象。最好的方法是使用 using
指令,如下所示:
using (Bitmap im = new Bitmap(reader["imgPath"].ToString()))
pB.Image = new Bitmap(im);
通常,您应该始终清理您创建的图像对象。请注意,这实际上是在新的 32bppARGB 图像上绘制图像,从而丢失图像的任何原始格式。尽管在您的情况下我认为这无关紧要,因为它只是为了在 UI 上显示。 (请注意,如果您确实需要一个完整的 1:1 图像数据克隆而没有任何流或文件链接,有一些方法可以做到这一点,但是 they're slightly more advanced。)
所以我用图像填充浮动布局面板,代码如下:
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 is used by another process"
要删除图像,我使用以下代码:
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 旁边我还能做些什么来摆脱面板内的图像。
但他们似乎在某个地方出现了鬼影。
对此有什么想法吗?
打开图像时要记住的基本规则如下:
- 从文件 will lock the file during the life cycle of the image object 创建的
Image
对象,防止文件被覆盖或删除,直到图像被释放。 - 从流 will need the stream to remain open for the entire life cycle of the image object 创建的
Image
对象。与文件不同,没有任何主动强制执行这一点,但在流关闭后,图像在保存、克隆或以其他方式操作时会出错。
(如果你想知道,Image.FromFile(String filename)
实际上只是 new Bitmap(String filename)
构造函数的包装器。我个人建议不要使用 Image.FromFile
,因为它失去了更精确的 Bitmap
返回对象的类型。)
至于你的问题,似乎处理 PictureBox
并没有处理实际图像。这可能可以通过首先显式处理 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 image)
构造函数从中创建一个新位图,然后处理从文件初始化的位图对象。最好的方法是使用 using
指令,如下所示:
using (Bitmap im = new Bitmap(reader["imgPath"].ToString()))
pB.Image = new Bitmap(im);
通常,您应该始终清理您创建的图像对象。请注意,这实际上是在新的 32bppARGB 图像上绘制图像,从而丢失图像的任何原始格式。尽管在您的情况下我认为这无关紧要,因为它只是为了在 UI 上显示。 (请注意,如果您确实需要一个完整的 1:1 图像数据克隆而没有任何流或文件链接,有一些方法可以做到这一点,但是 they're slightly more advanced。)