Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Remove FILE LOCKS? C#

Tags:

c#

file

file-io

So I am using C# and am making an enrollment system. So there is an option to add a picture and what I do, I prompt the user to pick a file and that file will then be Copied to the Directory folder and then renamed into the student's admission number. Here is the code for that browse button:

OpenFileDialog openDlg = new OpenFileDialog();
            openDlg.Filter = "All JPEG files (*.jpg; *.jpeg)| *.jpg; *.jpeg";
            string filter = openDlg.Filter;
            openDlg.Multiselect = false;
            openDlg.Title = "Open a JPG File";
            if (openDlg.ShowDialog() == DialogResult.OK)
            {                
                curFileName = openDlg.SafeFileName;
                string curFilePath = openDlg.FileName;

                openDlg.Dispose();

                string sourcePath = @curFilePath.Remove((curFilePath.Length - curFileName.Length));
                string targetPath = "@";

                mycon.Open();
                string cmdstr = "SELECT imageDirectory from userSettings WHERE ID = 1";
                cmd = new OleDbCommand(cmdstr, mycon);
                dr = cmd.ExecuteReader();
                while (dr.Read())
                {
                    targetPath = (@dr["imageDirectory"].ToString());
                }
                dr.Close();
                mycon.Close();

                string sourceFile = Path.Combine(sourcePath, curFileName);
                string destFile = Path.Combine(targetPath, curFileName);

                File.Copy(sourceFile, destFile, true);

                newname = @destFile.Remove((destFile.Length - curFileName.Length)).ToString() + "\\" + (DateTime.Now.Year + "-" + textBox1.Text+".jpeg");

                if (File.Exists(newname) == true)
                {
                    pictureBox1.Image.Dispose();
                    try
                    {
                        File.Delete(newname);
                    }

                    catch (IOException ex)
                    {
                        MessageBox.Show(ex.ToString());
                        return;
                    }
                }

                File.Move(destFile, newname);

                photoPath = newname;
                pictureBox1.Image = Image.FromFile(photoPath);

The problem are:

a.) I have a function to allow the user to go to the next step and then if he wants to do some changes in the last step he could go back and update it. The problem here is when he changes the picture, I get an error stating "The file cannot be accessed because it is being used by another process"

b.) When the user already uploaded a picture and then went back to the home page, he won't be able to upload a new picture when he decides to enroll again as well with an error stating: "The file cannot be accessed because it is being used by another process".

The two errors both point here :

`File.Delete(newname);`

I really don't know what to do guys I have been looking for a solution to this since last night and I can't see a solution that wouldn't get me to change the whole code altogether. please help :(

like image 805
John Ernest Guadalupe Avatar asked Oct 14 '12 05:10

John Ernest Guadalupe


2 Answers

Your code is correct, ignore the put-down about code smell. Disposing the PictureBox.Image is important to avoid out-of-memory exceptions.

This problem is caused by an implementation detail of the Bitmap class. When you open an image file, the class creates a memory-mapped file to map the pixel data of the image into memory. This was an important optimization for large images, it keeps the pixel data out of the paging file. It is not quite as important these days, 15 years after GDI+ was designed, modern machines have lots of RAM and disk space.

That memory-mapped file however creates a lock on the file. Important to prevent any other process with messing with the file data and invalidating the mapped view of the file. Which is what you are seeing, trying to replace or delete the file no longer works. You avoid it by creating a deep copy of the bitmap, a copy that has all of the pixel data in memory and no longer uses the file. Like this:

public static Bitmap LoadBitmapNolock(string path) {
    using (var img = Image.FromFile(path)) {
        return new Bitmap(img);
    }
}

Do note that the odds of running out of memory with large images on a 32-bit version of Windows is significantly increased with this code.

like image 130
Hans Passant Avatar answered Oct 22 '22 11:10

Hans Passant


Manual use of .Dispose() in a managed language (like C#) is a Code Smell. You are probably ending up in some invalid state because you're trying to manually manage resources. Two ways that you may be able to avoid this are:

  1. Get rid of the unneeded .Dispose() elements (like opnDlg.Dispose()), and/or
  2. Try wrapping your objects that need disposing in a using(...){...} statement

either way, once you've refactored your code there shouldn't be any .Dispose() method calls in it. The objects that you are using either don't need to be manually managed, and trying to do so can only lead to problems, or they absolutely need to be managed, and therefore the using(...) statement is far superior because it guarantees releasing of the resource when exiting the code block.

like image 42
Matt Klein Avatar answered Oct 22 '22 10:10

Matt Klein