Удаление файла, отображаемого в picturebox

Я выбираю файл из openfiledialoge и отображаю его в picturebox и его имя в текстовом поле, когда я нажимаю на delete кнопка, Я получаю исключение The process cannot access the file because it is being used by another process. Я много искал это исключение, чтобы получить разрешение, но я не штрафовал никого из них, когда я попытался закрыть файл с imagename, который находится в textbox i.e файл, который я показываю в picturebox; используя IsFileLocked метод, это закрывает и удаляет все файлы определенного пути к каталогу, но как я могу удалить только показанный файл в picturebox, где я ошибаюсь

     public partial class RemoveAds : Form
    {
        OpenFileDialog ofd = null;
        string path = @"C:UsersMonikaDocumentsVisual Studio 2010ProjectsOnlineExamOnlineExamImage"; // this is the path that you are checking.

        public RemoveAds()
        {
            InitializeComponent();
        }


        private void button1_Click(object sender, EventArgs e)
        {
            if (System.IO.Directory.Exists(path))
            {
                 ofd = new OpenFileDialog();
                ofd.InitialDirectory = path;
                DialogResult dr = new DialogResult();
                if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    Image img = new Bitmap(ofd.FileName);
                    string imgName = ofd.SafeFileName;
                    txtImageName.Text = imgName;
                    pictureBox1.Image = img.GetThumbnailImage(350, 350, null, new IntPtr());
                    ofd.RestoreDirectory = true;
                }
            }
            else
            {
                return;
            } 
        }
private void button2_Click(object sender, EventArgs e)
        {
            //Image img = new Bitmap(ofd.FileName);
            string imgName = ofd.SafeFileName;  
             if (Directory.Exists(path))
             {

                 var directory = new DirectoryInfo(path);
                 foreach (FileInfo file in directory.GetFiles())
                 { if(!IsFileLocked(file))
                     file.Delete(); 
                 }
             }


        }
        public static Boolean IsFileLocked(FileInfo path)
        {
            FileStream stream = null;   
            try
            { //Don't change FileAccess to ReadWrite,
                //because if a file is in readOnly, it fails.
                stream = path.Open ( FileMode.Open, FileAccess.Read, FileShare.None ); 
            } 
            catch (IOException) 
            { //the file is unavailable because it is:
                //still being written to or being processed by another thread
                //or does not exist (has already been processed)
                return true;
            } 
            finally
            { 
                if (stream != null)
                    stream.Close();
            }   
            //file is not locked
            return false;
        }
    }

заранее спасибо за любую помощь

5 ответов


(ранее) принятый ответ на этот вопрос-очень плохая практика. Если ты ... --9-->читать документацию on System.Drawing.Bitmap, в частности, для перегрузки, что создает растровое изображение из файла, вы найдете :

файл остается заблокированным, пока растровое изображение не будет удалено.

в коде вы создаете растровое изображение и сохраняете его в локальной переменной, но никогда не избавляетесь от него, когда закончите. Это означает, что ваш объект image вышел области, но не выпустил свою блокировку на файл изображения, который вы пытаетесь удалить. Для всех объектов, реализующих IDisposable (типа Bitmap) вы должны избавиться от них сами. См.этот вопрос например (или поиск других-это очень важная концепция!).

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

 if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
 {
      Image img = new Bitmap(ofd.FileName);  // create the bitmap
      string imgName = ofd.SafeFileName;
      txtImageName.Text = imgName;
      pictureBox1.Image = img.GetThumbnailImage(350, 350, null, new IntPtr());
      ofd.RestoreDirectory = true;
      img.Dispose();  // dispose the bitmap object
 }

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

кроме того, если вы хотите удалить только один file (растровое изображение, которое вы отобразили) ваш код удаления неверен и также удалит каждый файл в каталоге (это просто повторение точки Адель). Далее, вместо того, чтобы держать глобальный OpenFileDialog объект живой просто для хранения имени файла, я бы предложил избавление от этого и сохранение только информации о файле:

FileInfo imageFileinfo;           //add this
//OpenFileDialog ofd = null;      Get rid of this

private void button1_Click(object sender, EventArgs e)
{
     if (System.IO.Directory.Exists(path))
     {
         OpenFileDialog ofd = new OpenFileDialog();  //make ofd local
         ofd.InitialDirectory = path;
         DialogResult dr = new DialogResult();
         if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
         {
              Image img = new Bitmap(ofd.FileName);
              imageFileinfo = new FileInfo(ofd.FileName);  // save the file name
              string imgName = ofd.SafeFileName;
              txtImageName.Text = imgName;
              pictureBox1.Image = img.GetThumbnailImage(350, 350, null, new IntPtr());
              ofd.RestoreDirectory = true;
              img.Dispose();
         }
         ofd.Dispose();  //don't forget to dispose it!
     }
     else
     {
         return;
     }
 }

затем во втором обработчике кнопки вы можете просто удалить один файл, который вас интересует.

        private void button2_Click(object sender, EventArgs e)
        {                
           if (!IsFileLocked(imageFileinfo))
            {                 
                imageFileinfo.Delete();
            }
        }

используйте этот код

string imgName = ofd.SafeFileName;
            if (Directory.Exists(path))
            {

                var directory = new DirectoryInfo(path);
                foreach (FileInfo file in directory.GetFiles())
                {
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                        file.Delete();
                }
            }

ваш обработчик событий button2_Click циклически просматривает все файлы внутри вашего каталога и выполняет удаления.

вам нужно изменить свой код следующим образом:

 public partial class RemoveAds : Form
{
    OpenFileDialog ofd = null;
    string path = @"C:\Users\Monika\Documents\Visual Studio 2010\Projects\OnlineExam\OnlineExam\Image\"; // this is the path that you are checking.
    string fullFilePath;

    public RemoveAds()
    {
        InitializeComponent();
    }


    private void button1_Click(object sender, EventArgs e)
    {
        if (System.IO.Directory.Exists(path))
        {
             ofd = new OpenFileDialog();
            ofd.InitialDirectory = path;
            DialogResult dr = new DialogResult();
            if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                Image img = new Bitmap(ofd.FileName);
                string imgName = ofd.SafeFileName;
                txtImageName.Text = imgName;
                pictureBox1.Image = img.GetThumbnailImage(350, 350, null, new IntPtr());
                fullFilePath = ofd.FilePath;
                ofd.RestoreDirectory = true;
            }
        }
        else
        {
            return;
        } 
    }

    private void button2_Click(object sender, EventArgs e)
        {
             FileInfo file = new FileInfo(fullFilePath);

             if(!IsFileLocked(file))
                 file.Delete(); 
         }


    }

    public static Boolean IsFileLocked(FileInfo path)
    {
        FileStream stream = null;   
        try
        { //Don't change FileAccess to ReadWrite,
            //because if a file is in readOnly, it fails.
            stream = path.Open ( FileMode.Open, FileAccess.Read, FileShare.None ); 
        } 
        catch (IOException) 
        { //the file is unavailable because it is:
            //still being written to or being processed by another thread
            //or does not exist (has already been processed)
            return true;
        } 
        finally
        { 
            if (stream != null)
                stream.Close();
        }   
        //file is not locked
        return false;
    }
}

используя GetThumnailImage, вы должны указать ширину и высоту, которые являются статическими. Вместо этого используйте метод Load. например: имя picturebox1.Загрузка (путь к изображению); с помощью этого u не будет иметь никаких проблем в удалении изображения или папки перед закрытием приложения. никаких других методов создавать не нужно. надеюсь, это поможет


у меня была та же проблема : я загрузил файл в PictureBox и при попытке удалить его я получил то же исключение.
Это происходило только при отображении изображения.
Я перепробовал их все:--11-->

picSelectedPicture.Image.Dispose();
picSelectedPicture.Image = null;
picSelectedPicture.ImageLocation = null;  

и все равно получил то же исключение.
Затем я нашел это на CodeProject:[c#] удалить изображение, которое открывается в picturebox.
Вместо использования PictureBox.Load() создает Image из файла и определяет его как PictureBox.Image:

...
// Create image from file and display it in the PictureBox
Image image = GetCopyImage(imagePath);
picSelectedPicture.Image = image;
...  

private Image GetCopyImage(string path) {
    using (Image image = Image.FromFile(path)) {
        Bitmap bitmap = new Bitmap(image);
        return bitmap;
    }
}  

больше никаких исключений при удалении файла.
ИМХО, это самое подходящее решение.

редактировать
Я забыл упомянуть, что вы можете безопасно удалить файл после дисплея :

...
// Create image from file and display it in the PictureBox
Image image = GetCopyImage(imagePath);
picSelectedPicture.Image = image;
System.IO.File.Delete(imagePath);
...