Файл используется двумя процессами - PullRequest
2 голосов
/ 24 июля 2011

Я пытаюсь написать код, который удаляет изображение с жесткого диска, когда пользователь нажимает какую-либо кнопку удаления. Иногда я получаю следующее исключение, а иногда нет. И когда я действительно это делаю, если я пытаюсь удалить его снова, он работает большую часть времени.

Это исключение:

System.IO.IOException: процесс не может получить доступ к файлу, потому что он используется другим процессом.

Полагаю, я должен предоставить некоторые подробности о том, что именно происходит:

  • Пользователь загружает изображение, которое затем отображается на экране, чтобы пользователь мог видеть, что он / она только что загрузил.
  • Кнопка удаления показывается пользователю, если он / она решает, что он действительно не хочет загружать это изображение.
  • Когда пользователь нажимает кнопку удаления, я вызываю метод, который удаляет изображение и все его ранее созданные большие пальцы.
  • Наконец, изображение удаляется с экрана, и пользователь может загружать другие изображения.

Я не уверен, как я мог решить эту проблему, потому что исключение не предоставляет никакой информации о том, какой другой процесс удерживает файл. Есть идеи?

UPDATE:

    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 ]

5 голосов
/ 24 июля 2011

Вы не утилизируете ресурсы, с которыми работаете, используя свой метод 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 Framework. Он называется File.WriteAllBytes :

public void SaveImage(byte[] toSave, string path)
{
    File.WriteAllBytes(path, toSave);
}
0 голосов
/ 24 июля 2011

Чтобы найти информацию о том, что другой процесс удерживает в файле, вы должны использовать такой инструмент, как ProcessExplorer (sysinternals.com).Он имеет эту удобную функцию поиска («Найти»> «Найти дескриптор» или «DLL»), где вы вводите строку, такую ​​как имя файла, и он будет искать все дескрипторы и сообщать вам, какой процесс имеет открытый дескриптор.

Часто, когда я сталкиваюсьнеожиданная ошибка, как твоя, это первое место, куда я иду.

Надеюсь, это поможет,

Джон

0 голосов
/ 24 июля 2011

Во время процедуры загрузки вы используете оператор using для чтения файлов?если нет, то файловый ресурс не возвращается в ОС, поэтому он все еще «используется».

...