Let’s say there are two functions,
to be called after
Foo1, and only
Foo1 can call
A realistic scenario might be when
Foo1 is invoked using a
Foo1 is called and needs to return as quickly as possible so that
the calling client doesn’t hang. This means both
Foo2 must be asynchronous
functions, and that
Foo2 must run after
Foo1 has returned.
Foo1 to be able to call
Foo1 returns can be
done in multiple ways. One way might be to have external queue into which tasks
can be inserted so that they can be run when a certain state is set by a
separate thread. This is good for scalable enterprise architecture, but seems a
bit of an overkill when all we want to do is to call
Another way is using the timer object. A third way is using
the relatively new ‘async’ method modifier.
The “async” function modifier was introduced in Visual Studio
Before talking more about the async modifier, here is a complete listing of the code that is also attached to this tip. It's a console application:
public static string Strings = new string;
public static int Count = 0;
private async Task Foo2()
Strings[Count++] = "Foo2 called at " + DateTime.Now.Ticks;
public async Task Foo1()
Strings[Count++] = "Foo1 at " + DateTime.Now.Ticks;
Strings[Count++] = "End of Foo1 at " + DateTime.Now.Ticks;
static void Main(string args)
MyClass myclass = new MyClass();
while (MyClass.Count != 3) Thread.Sleep(1);
foreach (string msg in MyClass.Strings)
Foo1() is called asynchronously from the
Main function, it could be called from a web service method which needs to return back to a client as quickly as possible so the client doesn't seem to hang.
Foo2() is a
private function that will need to be called after
Foo2 is partially executed so that
Foo1 can return. This partial execution is just
Foo2 to temporarily exit so that
Foo1 can finish. The "
Yield" method, as described by Microsoft, "creates an awaitable task that asynchronously yields back to the current context when awaited." That's exactly what we would like to do. There are other ways to do this. Using a delay. The problem with that approach is the behavior of the code may change depending on how fast your computer is. This is easy to test. If you use
Task.Delay(1), which is 1 millisecond, it is more than enough to make the code above seem to be behaving the same. If you change the
Delay parameter to a
TimeSpan object with 1 tick, you may see that the code no longer works as expected.
When you run the code above (ctrl-F5), you should see something similar to:
Foo2 is called after
Foo1. Note the tick difference, about 20,000. On my machine, that's about 3200th of a second. So a delay of 1 second would seem to work, but certainly not 1 tick. As an exercise, change the code "
await Task.Yield()" to "
await Task.Delay(1)" and you'll likely see that
Foo2 is called after
Foo1. Now change it to "
await Task.Delay(TimeSpan.FromTicks(1))". You will see that
Foo2 is called before "
End of Foo1". This is because
await took less time than
Foo1 could return.