Azoul54
Azoul54

Reputation: 31

Error message 'Can't write to textfile: File is being used by another process'

I have one problem with my C# form. I have a textbox, used to add the content when I click on a button to an external txt file and a combobox which displays the txt file content.

My code:

String PathFile = @"Mypath";

private void button1_Click(object sender, EventArgs e)
{
    StreamWriter sw = new StreamWriter(PathFile);
    sw.WriteLine(textBox1.Text);
    sw.Close();
}

private void Form1_Load(object sender, EventArgs e)
{
    try
    {

        StreamReader sr = new StreamReader(PathFile);
        string line = sr.ReadLine();
        while (line != null)
        {
            comboBox1.Items.Add(line);
            line = sr.ReadLine();
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show("Error : " + ex.Message);
    }
}

The combobox works great and displays the content, but when I try to add a new entry with the textbox, the result is the following.

system.io.ioexception the process cannot access the file because it is being used by another process

I understand that the file is locked by the process for the combobox, but what can I do to resolve this situation?

Upvotes: 1

Views: 4553

Answers (5)

Moo-Juice
Moo-Juice

Reputation: 38820

You are not disposing of the StreamReader during your form load.

using(StreamReader sr = new StreamReader(PathFile))
{
    string line = sr.ReadLine();
    while (line != null)
    {
        comboBox1.Items.Add(line);
        line = sr.ReadLine();
    }
}

Also, when you're using the StreamWriter to write data to the file, you also need to dispose of the stream:

using(StreamWriter sw = new StreamWriter(PathFile))
{ 
    sw.WriteLine(textBox1.Text);
}

So what does using do? It's quite a neat construct. It takes an IDisposable and ensures that the object is disposed whether the code reaches the end of the using block, or an exception is thrown. We need to dispose of things like streams because they hold unmanaged resources (e.g. file handles), and we don't want to wait for the garbage collector to kick in and actually free the handle.

using is semantically equivalent to:

IDisposable someObjectThatIsDispoable; // e.g. StreamWriter/StreamReader, et al
try
{
     // your code here
}
finally
{
    if(someObjectThatIsDisposable != null)
        someObjectThatIsDisposable.Dispose();
}

Also, dispose takes care of closing the file, so the call to Close is unnecessary (hence they have been removed from this answer).

Upvotes: 9

ProgramFOX
ProgramFOX

Reputation: 6390

You didn't dispose the StreamReader. Try this:

private void Form1_Load(object sender, EventArgs e)
{
    StreamReader sr = null; // declare the StreamReader outside the try-catch-finally block
    try
    {

        sr = new StreamReader(PathFile);
        string line = sr.ReadLine();
        while (line != null)
        {
            comboBox1.Items.Add(line);
            line = sr.ReadLine();
        }

    }
    catch (Exception ex)
    {
        MessageBox.Show("Error : " + ex.Message);
    }
    finally
    {
        if (sr != null)
        {
             sr.Dispose(); // dispose the StreamReader if it's not null
        }
    }
}

Upvotes: 1

keyboardP
keyboardP

Reputation: 69372

As mentioned in the other answers, you're getting that error because your stream is not being closed. However, you can avoid explicitly using a StreamReader and also shorten your code by using File.ReadAllLines instead.

try
{
    foreach(string line in File.ReadAllLines(PathFile))
    {
       comboBox1.Items.Add(line);           
    }

}
catch (Exception ex)
{
    MessageBox.Show("Error : " + ex.Message);
}

Although not always necessarily, it's often a good idea to use a using block when dealing with classes that implement IDisposable. So for your StreamWriter, you could use this

using(StreamWriter sw = new StreamWriter(PathFile))
{
   sw.WriteLine(textBox1.Text);
}

This ensures that the stream is closed and the StreamWriter object is disposed.

Upvotes: 3

Steve
Steve

Reputation: 216313

The correct way to open/close a Stream is through the using statement.

In your Form_Load

 using(StreamReader sr = new StreamReader(PathFile))
 {
    string line = sr.ReadLine();
    while (line != null)
    {
        comboBox1.Items.Add(line);
        line = sr.ReadLine();
    }
 }

This will ensure the proper closing and disposing of the StreamReader at the closing braces also in case of exceptions inside the using block

Of course, you should change in the same way also the Button_Click code

private void button1_Click(object sender, EventArgs e)
{
    using(StreamWriter sw = new StreamWriter(PathFile))
    {
         sw.WriteLine(textBox1.Text);
    }
    // No really needed to call close
}

Upvotes: 4

Nikhil Agrawal
Nikhil Agrawal

Reputation: 48560

Release file by calling dispose on StreamWriter of load method.

private void Form1_Load(object sender, EventArgs e)
{
    StreamReader sr = new StreamReader(PathFile);
    try
    {
        string line = sr.ReadLine();
        while (line != null)
        {
            comboBox1.Items.Add(line);
            line = sr.ReadLine();
        }
        sr.Dispose();
        sr = null; 
    }
    catch (Exception ex)
    {
        MessageBox.Show("Error : " + ex.Message);
    }
    finally //Just in case any exception is thrown.
    {
       if (sr != null)
           sr.Dispose();
           sr = null;
    }
}

Upvotes: 1

Related Questions