Reputation: 7278
I know that you cannot have GUI controls to work in a separate thread. On my form load I would like to read from a text file and then display the contents in a rich text box. I do the reading in a separate thread but since eventually I would like this text to appear on my Rich Textbox, my window still freezes and my loading spinner does not animate.
private async void PreviewFileForm_Load(object sender, EventArgs e)
{
string fileName = Path.GetFileName(this.filePath);
lblFileName.Text = fileName;
richtxtboxPreview.Visible = false;
string fileContents = await ReadFileAsync(this.filePath);
richtxtboxPreview.Text = fileContents;
richtxtboxPreview.Visible = true;
spinnerLoadFile.Visible = false;
}
async Task<string> ReadFileAsync(string filePath)
{
string s = String.Empty;
await Task.Run(() =>
{
using (StreamReader sr = File.OpenText(filePath))
{
s = sr.ReadToEnd();
}
});
return s;
}
What can I do so that my loading bar spins to indicate waiting for the file to be read and then the rich text box show the result?
Upvotes: 0
Views: 907
Reputation: 109547
You can use async file I/O to do this. Here's a Microsoft sample.
So if you implement your async file reader like this (change the encoding to be the right kind for your text file; this code is copied verbatim from the Microsoft sample linked above):
private async Task<string> readFileAsync(string filePath)
{
using (FileStream sourceStream = new FileStream(filePath,
FileMode.Open, FileAccess.Read, FileShare.Read,
bufferSize : 4096, useAsync : true))
{
StringBuilder sb = new StringBuilder();
byte[] buffer = new byte[0x1000];
int numRead;
while ((numRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
// Use correct encoding here; maybe you need Encoding.UTF8
string text = Encoding.Unicode.GetString(buffer, 0, numRead);
sb.Append(text);
}
return sb.ToString();
}
}
You should just be able to call it as you already are.
However, I've sometimes had weird things happen when doing stuff from the Load event.
In some cases, I fixed such problems by putting the code into a separate method and using BeingInvoke() to call it from the Load method, e.g.:
private void PreviewFileForm_Load(object sender, EventArgs e)
{
this.BeginInvoke(new Action(doIt));
}
private async void doIt()
{
string fileName = Path.GetFileName(this.filePath);
lblFileName.Text = fileName;
richtxtboxPreview.Visible = false;
string fileContents = await ReadFileAsync(this.filePath);
richtxtboxPreview.Text = fileContents;
richtxtboxPreview.Visible = true;
spinnerLoadFile.Visible = false;
}
Upvotes: 1