Emmanuel Gomez
Emmanuel Gomez

Reputation: 1

IOException caused by file being in use

I have a problem that I know people already asked here but I tried the solution they bring but it's not helping.

My problem: I'm doing a program in C# with 2 forms. My main form is used to read a file .txt and put the information in a DataGridView:

public void LireFichier()
    {
        DataGridView dataGridView1 = new DataGridView();

        string delimeter = ";";
        string tableName = "Clients";
        string filePath = @"C:...\Clients.txt";

        DataSet dataset = new DataSet();

        using (StreamReader sr = new StreamReader(filePath))
        {
            dataset.Tables.Add(tableName);
            dataset.Tables[tableName].Columns.Add("ID");
            dataset.Tables[tableName].Columns.Add("Name");
            dataset.Tables[tableName].Columns.Add("LastName");
            dataset.Tables[tableName].Columns.Add("Datet");
            dataset.Tables[tableName].Columns.Add("Price");
            dataset.Tables[tableName].Columns.Add("Phone");
            dataset.Tables[tableName].Columns.Add("ID box");

            string allData = sr.ReadToEnd();
            string[] rows = allData.Split("\r".ToCharArray());

            foreach (string r in rows)
            {
                string[] items = r.Split(delimeter.ToCharArray());
                dataset.Tables[tableName].Rows.Add(items);
            }
            this.dataGridView1.DataSource = dataset.Tables[0].DefaultView;
         }

My second form is used to add a client in my .txt file :

      private void btn_Confirmer_Click(object sender, EventArgs e)
      {
        string filePath = @"...\Clients.txt";
        Client client = new Client();

        client.Id = idClient++;
        client.Name = tb_name.Text;
        client.LastName = tb_lastName.Text;

        client.Date = dtp_date.Value.ToString("dd-MMM-yyyy");
        client.Price = Convert.ToInt32(tb_price.Text);
        client.Phone = tb_telephone.Text;
        client.ID_Box = Convert.ToInt32(tb_idbox.Text);

        string clientInfo = client.Id.ToString() + ";" + client.Name.ToString() + ";" + client.LastName.ToString() + ";" + client.Date.ToString() + ";" +
                            client.Montant.ToString() + ";" + client.Phone.ToString() + ";" + client.ID_Boc.ToString() + ";";

        using (StreamReader sr = new StreamReader(filePath))
        {
            string allData = sr.ReadToEnd() + clientInfo;
            File.WriteAllText(filePath, allData);
        }

        this.Close();
      }

The problem remains in the StreamReader or the File.WriteAllText no matter what I do I always encounter the same exception(System.IO.IOException) that my file is in use when I arrived to write(add a client) in the file in my second form.

The solution that I tried are:

  1. put the using blocks
  2. sr.Close()
  3. sr.Dispose() even if I know that the using block call dispose at the end.
  4. sr.Close() and sr.Dispose() at the end of the instruction.

Upvotes: 0

Views: 66

Answers (4)

Trelly
Trelly

Reputation: 19

Try changing to the following since I think the write is interfering with the read you are already performing.

string allData; 
using (StreamReader sr = new StreamReader(filePath))
{
    allData = sr.ReadToEnd() + clientInfo;
}

this.Close();
File.WriteAllText(filePath, allData);

Upvotes: 2

Graffito
Graffito

Reputation: 1718

After ReadToEnd, close the StreamReader before WriteAllText:

using (StreamReader sr = new StreamReader(filePath))
{
    string allData = sr.ReadToEnd() + clientInfo;
    sr.Close() ; // <---- add this instruction
    File.WriteAllText(filePath, allData);
}

Upvotes: 0

Alexei - check Codidact
Alexei - check Codidact

Reputation: 23078

Trelly indicated the most possible cause of you problem (file already in use). However, the solution containing exception handling should look like this:

try 
{
    string allData = null; 
    using (var sr = new StreamReader(filePath))
    {
        allData = sr.ReadToEnd() + clientInfo;
    }

    File.WriteAllText(filePath, allData);
}
catch (IOException exc)
{
    // exception handling code
}

this.Close();

OR

It looks like you want to just append some text at the end of the file. File.AppendText is your friend:

using (StreamWriter sw = File.AppendText(filePath)) 
{
    sw.Write(clientInfo);
}

Upvotes: 1

Tomas Chabada
Tomas Chabada

Reputation: 3019

To make your blocks of code thread safe, I would use a lock statement. First declare object, you will perform lock on:

public static readonly Object Locker = new Object();

Then surround your parts of code, where you are working with file with lock statement:

lock(Locker)
{
   //perform file operations
}

Remember that both forms have to refer to the same Locker object

Upvotes: 0

Related Questions