vb.net – 如何防止Image.FromFile()方法锁定文件
我正在使用以下代码将JPG放入DataGridView的
Image单元格中.
If strFileName.ToLower.EndsWith(".jpg") Then Dim inImg As Image = Image.FromFile(strFileName) DataGridView4.Rows.Add() DataGridView4.Rows(DataGridView4.Rows().Count - 1).Cells(0).Value = inImg End If 问题是我需要从程序中保存这个文件,但我收到的消息是该文件正在被另一个程序使用. 所以我尝试在结束之前添加inImg.Dispose()if,但是然后程序不再在DataGridView中显示图像. 如何在不锁定它们的情况下在DataGridView中添加图像? 谢谢
当您使用Image.FromFile(strFileName)方法创建Image时,该方法将锁定该文件,直到您释放Image.确切原因解释如下.这就是为什么用这种方法不能多次访问同一个图像文件的原因.
你可以改为: >使用Image.FromStream(stream)方法. 以下是可能实现的自定义SafeImageFromFile方法,该方法不会锁定图像文件: Public Shared Function SafeImageFromFile(path As String) As Image Using fs As New FileStream(path,FileMode.Open,FileAccess.Read) Dim img = Image.FromStream(fs) Return img End using End Function 要么 Public Shared Function SafeImageFromFile(path As String) As Image Dim bytes = File.ReadAllBytes(path) Using ms As New MemoryStream(bytes) Dim img = Image.FromStream(ms) Return img End Using End Function 用法 If strFileName.ToLower.EndsWith(".jpg") Then Dim inImg As Image = SafeImageFromFile(strFileName) Dim index as integer = DataGridView4.Rows.Add() DataGridView4.Rows(index).Cells(0).Value = inImg End If 重要的提示 在这里,我使用Using语句创建FileStream或MemoryStream,以确保释放流.它在我的系统上工作正常,它似乎也适合你,虽然MSDN说Image.FromStream(stream)方法:
这句话的原因在这里解释:KB814675 Bitmap and Image constructor dependencies
因此,知道上面的代码可以生成GDIexceptions,因为使用Using释放流.从文件或图像创建过程中保存图像时可能会发生这种情况.从这个帖子Loading an image from a stream without keeping the stream open和Hans Passant的评论他们修复了Vista版gdiplus.dll中索引像素格式的几个问题,它只会在XP上发生. 为避免这种情况,您需要保持流打开.方法是: Public Shared Function SafeImageFromFile(path As String) As Image Dim fs As New FileStream(path,FileAccess.Read) Dim img = Image.FromStream(fs) Return img End Function 要么 Public Shared Function SafeImageFromFile(path As String) As Image Dim bytes = File.ReadAllBytes(path) Dim ms = New MemoryStream(bytes) Dim img = Image.FromStream(ms) Return img End Function 但是那些最后的方法有一些缺点,比如不释放流(内存问题),它们违反了规则CA2000 Dispose objects before losing scope. 知识库文章给出了一些解决方法:
以下是基于知识库文章的非索引图像创建实现和此答案https://stackoverflow.com/a/7972963/2387010您最好的选择是创建像素完美的图像副本 – 尽管YMMV(某些类型的图像可能有多个帧,或者您可能还必须复制调色板数据.)但对于大多数图像,这适用: Private Shared Function SafeImageFromFile(path As String) As Bitmap Dim img As Bitmap = Nothing Using fs As New FileStream(path,FileAccess.Read) Using b As New Bitmap(fs) img = New Bitmap(b.Width,b.Height,b.PixelFormat) Using g As Graphics = Graphics.FromImage(img) g.DrawImage(b,Point.Empty) g.Flush() End Using End Using End Using Return img End Function 有人表示重要的是FileStream以读模式打开(FileAccess.Read). 是的,但是如果你不使用Using语句并且不释放流,或者在多线程上下文中它会更加敏感:FileAccess.Write是不合适的,并且不需要FileAccess.ReadWrite,但打开流如果另一个程序(或多线程上下文中的程序)使用FileAccess.Read之外的其他模式打开文件,FileAccess.Read模式将不会阻止IO.Exception. 如果您希望能够显示图像并同时能够将数据保存到文件中,由于您没有使用这些方法锁定文件,您应该能够保存图像(删除/覆盖以前的图像) file)使用Image.Save方法. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |