MoralesJosue
MoralesJosue

Reputation: 199

Release image from process form PictureBox

I having trouble with error "System.IO.IOException: The process cannot access the file 'I:\User\Image\BarCodes\QTY.png' because it is being used by another process.at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)"

I know this error is caused because some other program of the same program is using the process, or at least that's what I think.

Here is the button that is causing this error

private void createbtn_Click(object sender, EventArgs e)
    {
        InsertBarCodeImage();

    }

private void InsertBarCodeImage()
    {
        try
        {
            if (qtytxt.Text !=  String.Empty)
            {
                Picturebox1.Image = null;

                BarCode insertBarCode = new BarCode();

                insertBarCode.InsertBarCode(qtytxt.Text, Picturebox1.Image);

                Picturebox1.Image = new Bitmap(insertBarCode.BARCODEQUANTITYNAMERUTE);

                Picturebox1.SizeMode = PictureBoxSizeMode.StretchImage;

                MessageBox.Show("Label created");

            }
            else
            {
                MessageBox.Show("Please enter qty", "Verify", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }
        catch (Exception e)
        {
            MessageBox.Show(e.ToString());
        }
    }

Class

class BarCode
{
    public string BARCODEQUANTITYNAMERUTE { get; set; }

    public void InsertBarCode(string quantity, Image quantityImage)
    {

        BARCODEQUANTITYNAMERUTE = @"I:\User\Image\BarCodes\QTY.png";

        try
        {

            Bitmap quantityBarCode = CreateBarCode("*" + quantity + "*");

            if (System.IO.File.Exists(BARCODEQUANTITYNAMERUTE))
                System.IO.File.Delete(BARCODEQUANTITYNAMERUTE);

            quantityBarCode.Save(BARCODEQUANTITYNAMERUTE, System.Drawing.Imaging.ImageFormat.Png);
            quantityImage = new Bitmap(BARCODEQUANTITYNAMERUTE);

        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }

    private Bitmap CreateBarCode(string text)
    {
        Bitmap barcode = new Bitmap(1, 1);
        const string freeThreeOfNine = "Free 3 of 9";
        Font fontthreeofnine = new Font(freeThreeOfNine, 40, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
        Graphics graphics = Graphics.FromImage(barcode);

        SizeF datasize = graphics.MeasureString(text, fontthreeofnine);

        barcode = new Bitmap(barcode, datasize.ToSize());

        graphics = Graphics.FromImage(barcode);

        graphics.Clear(Color.White);

        graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixel;

        graphics.DrawString(text, fontthreeofnine, new SolidBrush(Color.Black), 0, 0);

        graphics.Flush();

        fontthreeofnine.Dispose();
        graphics.Dispose();

        return barcode;
    }
}

So the error happens when the click event happens a second time, on line

if (System.IO.File.Exists(BARCODEQUANTITYNAMERUTE))
            System.IO.File.Delete(BARCODEQUANTITYNAMERUTE);

its trying to delete the previous image of the first click event, how can i stop the process so it is able to delete the image and re create it with the current Text value and show it on the PictureBox???

I'm using

PictureBox1.Image = null;

but no luck

Any help on this I would appreciate it.

Also if you could be nice enough to point out any good practices on the comments, it would help me out.

Edit (Help from @HansPassant) changed InsertBardCode in Class

public Image InsertBarCode(string barCodeString)
    {
        Bitmap barCodeImage = CreateBarCode("*" + barCodeString + "*");

        return barCodeImage;
    }

seams to work pretty good

Upvotes: 0

Views: 4414

Answers (4)

Berg Mann
Berg Mann

Reputation: 1

I had to combine sdev's and Nick_F's answers to both use a temp image, and dispose the original immediately, to remove the lock in time to (in my case) delete that original file (and avoid the System.IO.Exception).

var buttonImage = Image.FromFile(_settingsManager.LastPictureHiddenLocationSetting);

Bitmap tempImage = new Bitmap(buttonImage);

btnUndoHidePicture.BackgroundImage = tempImage;

buttonImage.Dispose();


Upvotes: 0

sdev
sdev

Reputation: 21

The best way to load an image without holding it is like this

Image tempImage = Image.FromFile("image.jpg");
Bitmap tempBitmap = new Bitmap(tempImage);
pictureBox.Image = tempBitmap;

Original source of the answer is here https://www.codeproject.com/Questions/492654/bc-dplusdeleteplusimagepluswhichplusisplusope

Upvotes: 2

Nick_F
Nick_F

Reputation: 1121

As Idle_Mind suggested, instead of Picturebox1.Image = null; you could use Picturebox1.Image.Dispose();

Upvotes: 2

Idle_Mind
Idle_Mind

Reputation: 39142

See the Bitmap Constructor Documentation that receives a file path:

The file remains locked until the Bitmap is disposed.

Since the bitmap is being used in the PictureBox, it hasn't been disposed and therefore the file is still locked causing your exception.

One fix is to create a new Bitmap from the first, then allow the first to dispose:

using (var img = new Bitmap(insertBarCode.BARCODEQUANTITYNAMERUTE))
{
    Picturebox1.Image = new Bitmap(img);
}

Upvotes: 2

Related Questions