10

我正在从 openfiledialoge 中选择文件并在图片框中显示它,并在单击delete按钮时在文本框中显示它的名称我得到异常The process cannot access the file because it is being used by another process. 我搜索了很多以解决这个异常但我没有很好地工作,当我尝试关闭时带有图像名的文件在文本框中,即我在图片框中显示的文件;使用IsFileLocked方法,这将关闭并删除特定目录路径的所有文件,但是如何删除图片框中显示的唯一文件,我出错了

     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.

        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;
        }
    }

提前感谢您的帮助

4

5 回答 5

6

这个问题的(以前)接受的答案是非常糟糕的做法。如果您阅读有关 的文档System.Drawing.Bitmap特别是从文件创建位图的重载,您会发现:

该文件保持锁定状态,直到释放位图。

在您的代码中,您创建位图并将其存储在局部变量中,但完成后您永远不会处理它。这意味着您的图像对象已超出范围,但尚未释放对您尝试删除的图像文件的锁定。对于所有实现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,如果您需要这样做以使事情正常进行,这应该是一个非常强烈的信号,表明您做错了其他事情。

此外,如果您只想删除一个文件(您显示的位图),您的删除代码是错误的,并且会删除目录中的每个文件(这只是重复 Adel 的观点)。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();
            }
        }
于 2013-08-07T13:02:02.400 回答
3

我遇到了同样的问题:我在PictureBox中加载了一个文件,当试图删除它时,我遇到了同样的异常。
这仅在显示图像时发生。
我都试过了:

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

仍然有同样的例外。
然后我在 CodeProject 上找到了这个:[c#] 删除在图片框中打开的图像
而不是使用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);
...  
于 2018-06-02T12:53:48.560 回答
0

使用此代码

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();
                }
            }
于 2013-08-02T05:25:50.447 回答
0

您的 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;
    }
}
于 2013-08-02T05:38:33.790 回答
0

通过使用 GetThumnailImage,您必须指定静态的宽度和高度。请改用 Load 方法。例如:pictureBox1.Load(图像的路径);通过使用这个你在关闭应用程序之前删除图像或文件夹没有问题。不需要创建其他方法。希望这可以帮助

于 2013-12-29T10:03:26.567 回答