Async 13: Expressions that contain await

Let’s keep up that async momentum.  It’s time to explore another set of Lucian’s online async samples. This time, it’s about expressions around an await.

The key concept here is you can substitute ‘await <SomeExpression>’ anywhere ‘<SomeExpression>’ is valid. The result of an await expression can be used anywhere that expression could be used.

For example, you can invoke members of the expression being awaited:

        public async void AsyncMemberAccessAround()
{
Console.WriteLine("Content length:");
Console.WriteLine(
(await new WebClient().DownloadStringTaskAsync
(new Uri("http://www.weather.gov")))
.Length);
}

Notice that the ‘.Length’ is a member of the expression ‘await new WebClient()..’. The asynchronous result has a Length property because the operation’s result has a Length property.

Similar to the last set of samples, Lucian runs through all the operators.  Some are particularly interesting, and I discuss those below:

If your async operation returns an Action or Func, you can invoke it when it is available:

        public async void AsyncInvocationAround()
{
Console.WriteLine((await PrecalculateCosineTableAsync())(0.0));
}

public async Task<Func<double, double>> PrecalculateCosineTableAsync()
{
await new SynchronizationContext().SwitchTo();

Thread.Sleep(1000); // Simulate precalculating a table of cosine values

return d =>
{
if (d == 0.0) return 1.0;
elsethrownew NotSupportedException();
};
}

The usual conversion operations behave as though the operation was synchronous:

ublic async void AsyncAsAround()
{
string str = await DeserializeAsync() asstring;
if (str != null)
{
Console.WriteLine(str);
}
else
{
Console.WriteLine("Deserialization failed.");
}
}

public async Task<object> DeserializeAsync()
{
await TaskEx.Delay(200); // Simulate loading an object from disk and deserializing it
return"serialized string";
}

Lucian also wrote several samples that generate numeric results. Those samples show that you can perform the usual mathematical operations on results that will be delivered in the future. Addition is one example:

        public async void AsyncBinaryMinusAround()
{
Console.WriteLine(await LongRunningOperation() - 5);
}

public async Task<int> LongRunningOperation()
{
Console.WriteLine("Attempting long-running operation...");

await new SynchronizationContext().SwitchTo();

// Simulate a process that takes between 2 and 4 seconds to complete.
Random r = new Random();
await TaskEx.Delay(r.Next(2000, 4000));

return 123;
}

Once again, the key lesson to learn from this set of samples is the integration of the async pattern into the familiar idioms of the C# language. That makes it easier to integrate the async pattern into your regular programming.

Created: 5/11/2011 6:56:38 PM

Current Projects

I create content for .NET Core. My work appears in the .NET Core documentation site. I'm primarily responsible for the section that will help you learn C#.

All of these projects are Open Source (using the Creative Commons license for content, and the MIT license for code). If you would like to contribute, visit our GitHub Repository. Or, if you have questions, comments, or ideas for improvement, please create an issue for us.

I'm also the president of Humanitarian Toolbox. We build Open Source software that supports Humanitarian Disaster Relief efforts. We'd appreciate any help you can give to our projects. Look at our GitHub home page to see a list of our current projects. See what interests you, and dive in.

Or, if you have a group of volunteers, talk to us about hosting a codeathon event.