Calling async methods from properties

I noticed that yesterday, someone read my post on Cancellation after searching the web to find out how to call async methods from properties. I am no expert on async code; I’ve just been playing with it for a while – since the 2nd Async CTP, but since I’ve never seen a post on this from my favourite author of async code articles, here are my thoughts on this.

You can’t mark either a property, nor it’s get/set assessors as async. I assume that’s the issue the person had. They can’t use the await keyword, because they can’t mark the code as async.

While I don’t know the Microsoft developer teams’ reasons for implementing it this way, I can guess: When a developer gets or sets a property, they expect it to be synchronous. It’s not the sort of place where anyone expects the code to go away to the netherworld, and return sometime in the future.

That said, there are async methods that you can call, but in the same context as event handlers, they need to be async void methods. That is, fire-and-forget async methods, not the type where you wait asynchronously for something to happen. And if you really… really.. have to use the await keyword in a property, or any other method that isn’t marked as async, you can, by putting it inside a lambda expression, but that’s really exactly the same as calling an async void method.

I’ve written a little console application to demonstrate:

async from properties
  1. using System;
  2. using System.Threading.Tasks;
  4. namespace Demo
  5. {
  6.     class Program
  7.     {
  8.         private string awesome = “awesome”;
  9.         private string awesome1 = “awesome1”;
  11.         public string Awesome
  12.         {
  13.             get { return awesome; }
  14.             set
  15.             {
  16.                 Console.WriteLine(“{0}Enter Awesome setter.”, FormattedDate());
  17.                 awesome = value;
  18.                 AweSomeSideEffect();
  19.                 Console.WriteLine(“{0}Exit Awesome setter.”, FormattedDate());
  20.             }
  21.         }
  23.         public string Awesome1
  24.         {
  25.             get { return awesome1; }
  26.             set
  27.             {
  28.                 Action sideEffect = async () =>
  29.                 {
  30.                     await Task.Delay(TimeSpan.FromSeconds(1D));
  31.                     Console.WriteLine(“\n{0}Awesome1 side-effect.\n”, FormattedDate());
  32.                 };
  34.                 Console.WriteLine(“{0}Enter Awesome1 setter.”, FormattedDate());
  35.                 awesome1 = value;
  36.                 sideEffect();
  37.                 Console.WriteLine(“{0}Exit Awesome1 setter.”, FormattedDate());
  38.             }
  39.         }
  41.         private async void AweSomeSideEffect()
  42.         {
  43.             await Task.Delay(TimeSpan.FromSeconds(3D));
  44.             Console.WriteLine(“\n{0}Awesome side-effect.\n”, FormattedDate());
  45.         }
  47.         private string FormattedDate()
  48.         {
  49.             return DateTime.Now.ToString(“yyyy-MM-dd HH:mm:ss\t”);
  50.         }
  52.         static void Main(string[] args)
  53.         {
  54.             var program = new Program();
  55.             program.Awesome = “Demo”;
  56.             Console.WriteLine();
  57.             program.Awesome1 = “Set”;
  58.             System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5D));
  59.             Console.ReadLine();
  60.         }
  61.     }
  62. }

The demo program has a class with two properties, Awesome and Awesome1.

When the Awesome property is set, it calls an async void method. When the Awesome1 property is set, it calls an async lambda. If you run the demo program, you should get output something like this:

2013-04-23 13:24:55 Enter Awesome setter.
2013-04-23 13:24:55 Exit Awesome setter.

2013-04-23 13:24:55 Enter Awesome1 setter.
2013-04-23 13:24:55 Exit Awesome1 setter.

2013-04-23 13:24:56 Awesome1 side-effect.

2013-04-23 13:24:58 Awesome side-effect.

As you can see, whether you call an async void method or a lambda expression, the code returns execution from the property setter immediately, while the async code continues to run in the background.


About Jerome

I am a senior C# developer in Johannesburg, South Africa. I am also a recovering addict, who spent nearly eight years using methamphetamine. I write on my recovery blog about my lessons learned and sometimes give advice to others who have made similar mistakes, often from my viewpoint as an atheist, and I also write some C# programming articles on my programming blog.
This entry was posted in Programming and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s