I'm looking at the new async
and await
keywords in C# and just trying to get a feel for them.
I'm looking at the MSDN FileStream.WriteAsync()
example, and I wasn't sure I understood something.
The example is as follows:
using System;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.IO;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
UnicodeEncoding uniencoding = new UnicodeEncoding();
string filename = @"c:\Users\exampleuser\Documents\userinputlog.txt";
byte[] result = uniencoding.GetBytes(UserInput.Text);
using (FileStream SourceStream = File.Open(filename, FileMode.OpenOrCreate))
{
SourceStream.Seek(0, SeekOrigin.End);
await SourceStream.WriteAsync(result, 0, result.Length);
}
}
}
}
What I don't get is the placement of the await
. It seems that you can't take the Task
item that is returned by WriteAsync()
because this always gives me a syntax error. So the only way I could get this to compile is by leaving the await
with the call.
But if you do this, does it not wait for the call to finish? This makes it not very asynchronous...
I suspect the problem is with your understanding of what await
does.
But if you do this, does it not wait for the call to finish? This makes it not very asynchronous...
When you await
something, you "block asynchronously" - your asynchronous function will continue when the asynchronous operation has completed, but the immediate call will complete immediately.
So in your case, the UI thread becomes unblocked because Button_Click
returns, but when the file write operation has completed, execution will return (still in the UI thread) to the end of the await
expression... you'll then close the FileStream
and complete the asynchronous function.
It would be clearer what was going on if you did something else after the await
expression (e.g. updating the UI). But yes, it really is asynchronous - it just allows you to write code which looks synchronous.
The await doesn't actually block while it's waiting. What happens is that the compiler does some complex stuff to make a so called continuation of all code after the await and tells the task to execute that continuation when it's completed.
Basically the last lines of the Button_Click method are translated to:
FileStream SourceStream = File.Open(filename, FileMode.OpenOrCreate);
SourceStream.Seek(0, SeekOrigin.End);
Task t = SourceStream.WriteAsync(result, 0, result.Length);
t.ContinueWith(_ => SourceStream.Dispose());
Of course, this is simplified as this will be executed more efficient if the WriteAsync completes immediately, for example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With