Reputation: 37
So I was trying out Windows forms for a school project and kept running into the error:
System.IO.IOException('The process cannot access the file 'C:\XXXX\YYYY.txt' because it is being used by another process.'
when trying to delete files (File.Delete(path);
) via a button_click
event.
Turns out, when I changed the following method from:
private void updateTxt(){
String tempStore = "";
iDLbl1.Text = "ID:" + id;//iDLbl1 is ID Label 1
try
{
StreamReader Reader = new StreamReader(path);
while (!Reader.EndOfStream)
{ tempStore += Reader.ReadLine() + "\n"; }
}
catch { noIDLbl.Visible = true; }
rTxtBox.Text = tempStore;//rTxtBox is Rich Text Box
}
to
private void updateTxt(){
String tempStore = "";
iDLbl1.Text = "ID:" + id;//iDLbl1 is ID Label 1
try
{
using(StreamReader Reader = new StreamReader(path))
{
while (!Reader.EndOfStream)
{ tempStore += Reader.ReadLine() + "\n"; }
}
}
catch { noIDLbl.Visible = true; }
rTxtBox.Text = tempStore;//rTxtBox is Rich Text Box
}
The exception stopped popping up. While the code works, I have no idea what causes this at all... The logic doesn't seem to click for me, so anyone knows why this happens or have a more logical solution?Ask for clarification if needed and Here's the constructor just in-case:
public FindID(String ID)
{
id = ID;
path = @"C:\XXXX\YYYY\"+ID+".txt";
InitializeComponent();
updateTxt();
}
Upvotes: 1
Views: 84
Reputation: 107297
In the your first approach, since you aren't Close()
ing or Dispose()
ing your StreamReader
, the associated file handle will be held until the StreamReader
is collected by the garbage collector, which could be many seconds, or even minutes later (and please don't try and control or influence the GC).
In your second approach, the using
scope Disposes (and closes) the StreamReader
at the end of the scope (the closing }
matching the using
), which is correct practice when using any class which implements IDisposable
. This then releases any handles to the file, allowing for its deletion. The using block also has the guarantees of a try / finally block, so Dispose
will be called even if there is an IO Exception:
using(StreamReader Reader = new StreamReader(path)) // try {StreamReader Reader = ...}
{
...
} <- equivalent to finally {Reader.Dispose();}
However, since you seem to just want to immediately materialize all lines from a line delimited text file, you can do this in one step with File.ReadAllLines - i.e. no need for StreamReader
at all:
var tempStore = string.Join(Environment.NewLine, File.ReadAllLines(path));
Upvotes: 6
Reputation: 9289
In the second code as soon your code block will execute StreamReader will be disposed. Since StreamReader will be disposed the file is not locked by your current process.
In your first code you can do same by dispose them at the end of your code.
Upvotes: 3