两个进程使用的文件

时间:2011-07-24 10:27:58

标签: c# asp.net file process io

我正在尝试编写一些代码,一旦用户点击某个删除按钮,该代码就会从硬盘上删除图像。有时我会得到以下异常,有时候我没有。当我真的这样做时,如果我再次尝试删除它,它大部分时间都可以工作。

这是一个例外:

  

System.IO.IOException:进程无法访问该文件,因为它   正在被另一个进程使用。

我想我应该提供一些有关正在发生的事情的细节:

  • 用户上传图片,然后在屏幕上显示,以便用户可以看到他/她刚刚上传的内容。
  • 如果用户确定他们并不想上传此图片,则会向用户显示删除按钮。
  • 当用户点击删除按钮时,我会调用删除图像及其之前创建的所有拇指的方法。
  • 最后,图像将从屏幕上删除,用户可以上传其他图像。

我不确定如何解决此问题,因为该异常未提供有关哪个其他进程保留在文件中的任何信息。有什么想法吗?

更新

    public byte[] ResizeImageToBytes(string path, int size, string name)
    {
        var newImage = Image.FromFile(path);
        int newWidth; int newHeight;
        if (size == 470)
        {
            if (newImage.Height != 250)
            {
                newWidth = (int)Math.Round(newImage.Width * (100 / (newImage.Height / 250)) * 0.01);
                newHeight = 250;
            }
            else
            {
                newWidth = newImage.Width;
                newHeight = newImage.Height;
            }
        }
        else
        {
            if (newImage.Width > newImage.Height)
            {
                newWidth = size;
                newHeight = newImage.Height*size/newImage.Width;
            }
            else
            {
                newWidth = newImage.Width*size/newImage.Height;
                newHeight = size;
            }
        }

        var thumb = new Bitmap(newWidth, newHeight);
        var gfx = Graphics.FromImage(thumb);
        gfx.CompositingQuality = CompositingQuality.HighQuality;
        gfx.SmoothingMode = SmoothingMode.HighQuality;
        gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;

        var rect = new Rectangle(0, 0, newWidth, newHeight);
        gfx.DrawImage(newImage, rect);
        var ms = new MemoryStream();
        thumb.Save(ms, newImage.RawFormat);
        return ms.GetBuffer();
    }

    public void SaveImage(byte[] toSave, string path)
    {
        using (var ms = new MemoryStream())
        {
            ms.Write(toSave, 0, toSave.Length);
            using(var theImage = Image.FromStream(ms)) 
            {
                theImage.Save(path);
            }
        }
    }

    [HttpPost]
    public ActionResult Upload()
    {
        var newFile = System.Web.HttpContext.Current.Request.Files["Filedata"];
        string guid = Guid.NewGuid() + newFile.FileName;
        string itemImagesFolder = Server.MapPath(Url.Content("~/Content/ItemImages/"));
        string fileName = itemImagesFolder + "originals/" + guid;
        newFile.SaveAs(fileName);

        string finalPath;
        foreach (var dim in ImageDimensionsList.Options)
        {
            var bytes = _imageService.ResizeImageToBytes(fileName, dim.Width, guid);
            finalPath = itemImagesFolder + dim.Title + "/" + guid;
            _imageService.SaveImage(bytes, finalPath);
        }
        return Content(guid);
    }

3 个答案:

答案 0 :(得分:5)

您没有在ResizeImageToBytes方法中处置您正在使用的任何可支配资源。这会在应用程序中留下泄漏的句柄,当然还有锁定的文件。试试这个:

public byte[] ResizeImageToBytes(string path, int size, string name)
{
    using (var newImage = Image.FromFile(path))
    {
        int newWidth; int newHeight;
        if (size == 470)
        {
            if (newImage.Height != 250)
            {
                newWidth = (int)Math.Round(newImage.Width * (100 / (newImage.Height / 250)) * 0.01);
                newHeight = 250;
            }
            else
            {
                newWidth = newImage.Width;
                newHeight = newImage.Height;
            }
        }
        else
        {
            if (newImage.Width > newImage.Height)
            {
                newWidth = size;
                newHeight = newImage.Height * size / newImage.Width;
            }
            else
            {
                newWidth = newImage.Width * size / newImage.Height;
                newHeight = size;
            }
        }

        using (var thumb = new Bitmap(newWidth, newHeight))
        using (var gfx = Graphics.FromImage(thumb))
        {
            gfx.CompositingQuality = CompositingQuality.HighQuality;
            gfx.SmoothingMode = SmoothingMode.HighQuality;
            gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;

            var rect = new Rectangle(0, 0, newWidth, newHeight);
            gfx.DrawImage(newImage, rect);
            using (var ms = new MemoryStream())
            {
                thumb.Save(ms, newImage.RawFormat);
                return ms.GetBuffer();
            }
        }
    }
}

就你的SaveImage方法而言,这个方法对我来说似乎是多余的,因为它已经存在于.NET框架中。它被称为File.WriteAllBytes

public void SaveImage(byte[] toSave, string path)
{
    File.WriteAllBytes(path, toSave);
}

答案 1 :(得分:0)

在上传例程中,您是否在文件阅读器周围使用using语句?如果不是,那么文件资源不会返回到OS,因此它仍然被“使用”。

答案 2 :(得分:0)

要查找有关其他进程保留在文件中的信息,您应该使用ProcessExplorer(sysinternals.com)之类的工具。它具有这个方便的搜索功能(查找>查找句柄或DLL),您可以在其中输入类似文件名的字符串,它将搜索所有句柄并告诉您哪个进程的句柄处于打开状态。

通常当我遇到像您这样的意外错误时,这是​​我去的第一个地方。

希望这有帮助,

约翰

相关问题