Function-A calling another function-B after A returns (both functions are Async)

Let’s say there are two functions, Foo1 and Foo2. Foo2 needs to be called after Foo1, and only Foo1 can call Foo2:

A realistic scenario might be when Foo1 is invoked using a web service. Foo1 is called and needs to return as quickly as possible so that the calling client doesn’t hang. This means both Foo1 and Foo2 must be asynchronous functions, and that Foo2 must run after Foo1 has returned.

For Foo1 to be able to call Foo2 after 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 overkill when all we want to do is to call Foo2—after Foo1.

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 2012/2013.

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:

 

using System; namespace MyCSasync { using System.Threading; using System.Threading.Tasks; class MyClass { public static string[] Strings = new string[3]; public static int Count = 0; private async Task Foo2() { await Task.Yield(); Strings[Count++] = “Foo2 called at ” + DateTime.Now.Ticks; } public async Task Foo1() { Strings[Count++] = “Foo1 at ” + DateTime.Now.Ticks; // Call Foo2 asynchronously AND after this function returns. Foo2(); Strings[Count++] =”End of Foo1 at ” + DateTime.Now.Ticks; } }class Program {staticvoid Main(string[] args) { MyClass myclass =new MyClass(); myclass.Foo1();while (MyClass.Count !=3) Thread.Sleep(1); foreach (string msgin MyClass.Strings) { Console.WriteLine(msg); } } } }

While 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 Foo1 completes.

Foo2 is partially executed so that Foo1 can return. This partial execution is just

await Task.Yield()

This allows 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, 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 Foo2’s await took less time than Foo1 could return.

Advertisements
By Sriramjithendra Posted in C#.NET

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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