File.Delete失败时Image.FromFile被称为它之前,尽管使得加载图像的副本,并销毁原始 [英] File.Delete failing when Image.FromFile was called prior it, despite making copy of loaded image and destroying original one

查看:244
本文介绍了File.Delete失败时Image.FromFile被称为它之前,尽管使得加载图像的副本,并销毁原始的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新时间:

我用以下解决方案(从流读取图像),但得到新的问题。 IMG对象是一个充满了正确的值的所有领域绝对正确的Image类的实例。但调用

I used below solutions (loading Image from stream), but get new problem. img object is absolutely correct Image class instance with all field filled with correct values. But calling

img.Save("path/to/new/image.bmp");

这是它导致了GDI +新的异常(System.Runtime.InteropServices.ExternalException,在GDI +接口) - 我得到错误信息,但在打磨,我不知道如何把它

on it results in new exception for GDI+ (System.Runtime.InteropServices.ExternalException, in GDI+ interface) - I get error message but is in polish, am not sure how to translate it.

原题

我有问题,C#.NET框架2.0

I have problem with C# .NET Framework 2.0

基本上我'努力实现:

Image img = Image.FromFile("Path/To/Image.bmp");
File.Delete("Path/To/Image.bmp"); // Exception, the file is in use!

对我来说,保持图像的副本在内存中,当原始文件被删除,这是非常重要的。不过,我觉得这是某种奇怪的是,.NET仍然锁定在硬盘中的文件,尽管它不再需要任何操作(整个图像现在是在内存中,是不是?)

It is important for me to keep copy of image in memory when original file was deleted. I though it is somehow odd that .NET still lock file on hard disc despite it is no longer required for any operation (entire image is now in memory, isn't it?)

所以,我想这个解决方案:

So I tried this solution:

Image img = new Image(Image.FromFile("Path/To/Image.bmp")); // Make a copy
                    // this should immiedietaly destroy original loaded image
File.Delete("Path/To/Image.bmp"); // Still exception: the file is in use!

我可以做的:

I can do:

Image img = null;
using(Image imgTmp = Image.FromFile("Path/To/Image.bmp"))
{
    img = new Bitmap(imgTmp.Width, imgTmp.Height, imgTmp.PixelFormat);
    Graphics gdi = Graphics.FromIage(img);
    gdi.DrawImageUnscaled(imgTmp, 0, 0);
    gdi.Dispose();
    imgTmp.Dispose(); // just to make sure
}
File.Delete("Path/To/Image.bmp"); // Works fine
// So I have img!

但是,这在我看来几乎就像使用核武器杀死臭虫......并提出了另一个问题:GDI支持不佳绘制基于调色板图像到对方(和调色板的是大部分在我的收藏)

But this seems to me almost like using nuke to kill bug... and raises another problem: GDI poorly support Drawing palette-based images onto each other (and palette ones are majority in my collection).

我是不是做错了什么?是什么更好的办法让图像在内存和硬盘中删除原始文件?

Am I doing something wrong? Is any better way to have Image in memory and original file deleted from hard disk?

推荐答案

这应该做的伎俩:

This should do the trick:

  Image img = null;
  using (var stream = File.OpenRead(path)) {
    img = Image.FromStream(stream);
  }
  File.Delete(path);

更新:不要使用上面的code

UPDATE: Don't use the code above!

我已经找到了相关的知识库文章: http://support.microsoft.com/? ID = 814675

I've found the related knowledge base article: http://support.microsoft.com/?id=814675

解决方案是真正的复制在文章中列出的位图。我有codeD的两种方式是,文中提到的(第一个是一个,你在做什么,第二个是一个在你的答案,但没有使用不安全):

The solution is to really copy the bitmap as outlined in the article. I've coded the two ways that the article mentions (the first one was the one you were doing, the second one is the one in your answer, but without using unsafe):

public static Image CreateNonIndexedImage(string path) { 
  using (var sourceImage = Image.FromFile(path)) { 
    var targetImage = new Bitmap(sourceImage.Width, sourceImage.Height, 
      PixelFormat.Format32bppArgb); 
    using (var canvas = Graphics.FromImage(targetImage)) { 
      canvas.DrawImageUnscaled(sourceImage, 0, 0); 
    } 
    return targetImage; 
  } 
} 

[DllImport("Kernel32.dll", EntryPoint = "CopyMemory")] 
private extern static void CopyMemory(IntPtr dest, IntPtr src, uint length); 

public static Image CreateIndexedImage(string path) { 
  using (var sourceImage = (Bitmap)Image.FromFile(path)) { 
    var targetImage = new Bitmap(sourceImage.Width, sourceImage.Height, 
      sourceImage.PixelFormat); 
    var sourceData = sourceImage.LockBits(
      new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), 
      ImageLockMode.ReadOnly, sourceImage.PixelFormat); 
    var targetData = targetImage.LockBits(
      new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), 
      ImageLockMode.WriteOnly, targetImage.PixelFormat); 
    CopyMemory(targetData.Scan0, sourceData.Scan0, 
      (uint)sourceData.Stride * (uint)sourceData.Height); 
    sourceImage.UnlockBits(sourceData); 
    targetImage.UnlockBits(targetData); 
    targetImage.Palette = sourceImage.Palette;
    return targetImage; 
  } 
} 

这篇关于File.Delete失败时Image.FromFile被称为它之前,尽管使得加载图像的副本,并销毁原始的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆