I have the following code,
private void button1_Click(object sender, RoutedEventArgs e)
{
button1.IsEnabled = false;
var s = File.ReadAllLines("Words.txt").ToList(); // my WPF app hangs here
// do something with s
button1.IsEnabled = true;
}
Words.txt
has a ton of words which i read into the s variable, I am trying to make use of async
and await
keywords in C# 5 using Async CTP Library
so the WPF app doesn't hang. So far I have the following code,
private async void button1_Click(object sender, RoutedEventArgs e)
{
button1.IsEnabled = false;
Task<string[]> ws = Task.Factory.FromAsync<string[]>(
// What do i have here? there are so many overloads
); // is this the right way to do?
var s = await File.ReadAllLines("Words.txt").ToList(); // what more do i do here apart from having the await keyword?
// do something with s
button1.IsEnabled = true;
}
The goal is to read the file in async rather than sync, to avoid freezing of WPF app.
Any help is appreciated, Thanks!
Try this:
Edit:
You don't need the try-finally for this to work. It's really only the one line that you need to change. To explain how it works: This spawns another thread (actually gets one from the thread pool) and gets that thread to read the file. When the file is finished reading then the remainder of the button1_Click method is called (from the GUI thread) with the result. Note that this is probably not the most efficient solution, but it is probably the simplest change to your code which doesn't block the the GUI.
I also encountered a problem described in your question. I've solved it just simplier that in previous answers:
Use Stream.ReadAsync for asynchronous reading of file,
Read MSDN Stream.ReadAsync
UPDATE: Async versions of
File.ReadAll[Lines|Bytes|Text]
,File.AppendAll[Lines|Text]
andFile.WriteAll[Lines|Bytes|Text]
have now been merged into .NET Core. These methods will hopefully be ported back to .NET Framework, Mono etc. and rolled into a future version of .NET Standard.Using
Task.Run
, which essentially is a wrapper forTask.Factory.StartNew
, for asynchronous wrappers is a code smell.If you don't want to waste a CPU thread by using a blocking function, you should await a truly asynchronous IO method,
StreamReader.ReadToEndAsync
, like this:This will get the whole file as a
string
instead of aList<string>
. If you need lines instead, you could easily split the string afterwards, like this:EDIT: Here are some methods to achieve the same code as
File.ReadAllLines
, but in a truly asynchronous manner. The code is based on the implementation ofFile.ReadAllLines
itself: