Async methods return type

 
One of the questions I am often asked about the async/await keywords is about the return type. Specifically about the void return type for async method. Here is a small explanation about the three possible return type :
 

Void

If an async method returns void, it can’t be awaited. It is a “fire and forget” mode, where the async method will run in parallel with the calling method. It should be avoided if possible because, as said, it is not awaitable (You have to return Task or Task to be awaitable). The main usage is for compatibility with event handlers which must return void.
Example with this code :
using System;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var instance = new TestAsync();

            instance.TestVoid();

            Console.ReadKey();
        }
    }


    public class TestAsync
    {
        async public void TestVoid()
        {
            Console.WriteLine("Before async method...");
            ReturnVoid();
            Console.WriteLine("After async method...");
        }

        async public void ReturnVoid()
        {
            Console.WriteLine("   Wait for 2 seconds...");
            await Task.Delay(2000);
            Console.WriteLine("   Wait is over...");
        }
    }
}

If you run it :

As you see, the Main method continues independently of the sync method

Task

You have to see it as Task. If your method returns nothing, then the async version should return Task so it will be awaitable.
Example :
using System;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var instance = new TestAsync();

            instance.TestVoidAwaitable();

            Console.ReadKey();
        }
    }


    public class TestAsync
    {
        async public void TestVoidAwaitable()
        {
            Console.WriteLine("Before async method...");
            await ReturnVoidAwaitable();
            Console.WriteLine("After async method...");
        }

        async Task ReturnVoidAwaitable()
        {
            Console.WriteLine("   Wait for 2 seconds...");
            await Task.Delay(2000);
            Console.WriteLine("   Wait is over...");
        }

    }
}
 
Result :

Task

If your method returns a type T, then the async version must return Task to be awaitable.
Example :
using System;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var instance = new TestAsync();

            instance.TestStringAwaitable();

            Console.ReadKey();
        }
    }


    public class TestAsync
    {
        async public void TestStringAwaitable()
        {
            Console.WriteLine("Before async method...");
            Console.WriteLine("      Method returns : " + await ReturnStringAwaitable());
            Console.WriteLine("After async method...");
        }

        async Task ReturnStringAwaitable()
        {
            Console.WriteLine("   Wait for 2 seconds...");
            await Task.Delay(2000);
            Console.WriteLine("   Wait is over...");
            return "Hello world!";
        }
    }
}
 
Result :
 
Pretty easy, just have to get used to return nothing or a type T when the method definition states it returns Task and Task respectively !
The following two tabs change content below.
Olivier

Olivier

Mobile Engineer at Arcana Studio
Freelance developer. Passionate for mobile Development and IoT. Expert in WinRT and Xamarin. MVP Windows Platform Development Nokia Developer Champion