Reputation: 31
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
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
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
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
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
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