Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Async method call all the way to Main

Tags:

c#

async-await

Can someone clarify this example, which of course, is not working:

class Program
{
    static void Main(string[] args)//main cant' be async
    {
        int res = test();//I must put await here

        Console.WriteLine("END");
    }

    public async static Task<int> test()
    { //why can't I make it just: public int test()??
        int a1, a2, a3, a4;

        a1 = await GetNumber1();
        a2 = await GetNumber2();
        a3 = await GetNumber3();

        a4 = a1 + a2 + a3;
        return a4;
    }

    public static async Task<int> GetNumber1()
    {
        await Task.Run(() =>
            {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("GetNumber1");
                    System.Threading.Thread.Sleep(100);
                }
            });
        return 1;
    }

I am trying to "collect" values from GenNumberX methods by using "await". I would like to make method "test" not async somehow. I dont understand why test has to be async when I am using await to get a value. This example makes me to write async on every method where I use async, and when I drill up to Main, I cannot make it async?

How to write real-world example:

public bool ReserveAHolliday()
{
        bool hotelOK = await ReserveAHotel();//HTTP async request
        bool flightOK = await ReserveFlight();////HTTP async request
        bool result = hotelOK && flightOK;
        return result;
}

How to make method ReserveAHolliday synchronous? Am I missing something or don't understand the use of async-await mechanism?

like image 799
vpetrovic Avatar asked Oct 19 '22 10:10

vpetrovic


1 Answers

below is a full example. you can run the ReserverAHoliday both Synchronously (bool r = ReserveAHolliday().Result;) and Asynchronously (just call ReserveAHolliday();) from MAIN (depends which line you comment). and you can see the effect ("END" gets printed before / after the reservation is complete). I prefer the await Task.WhenAll() methods, which is more readable. also note that it's preferred to use await Task.Delay(100) instead of Thread.sleep inside GetNumber1.

    class Program
{
    static void Main(string[] args)//main cant' be async
    {
        //int res = test().Result;//I must put await here
        bool r = ReserveAHolliday().Result; //this will run Synchronously.
        //ReserveAHolliday(); //this option will run aync : you will see "END" printed before the reservation is complete.
        Console.WriteLine("END");
        Console.ReadLine();
    }

    public async static Task<int> test()
    { //why can't I make it just: public int test()??
        //becuase you cannot use await in synchronous methods. 
        int a1, a2, a3, a4;

        a1 = await GetNumber1();
        a2 = await GetNumber1();
        a3 = await GetNumber1();

        a4 = a1 + a2 + a3;
        return a4;
    }

    public static async Task<int> GetNumber1()
    {
        //await Task.Run(() =>
        //    {
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine("GetNumber1");
                    await Task.Delay(100); // from what I read using Task.Delay is preferred to using  System.Threading.Thread.Sleep(100);
                }
        //    });
        return 1;
    }

    public async static Task<bool> ReserveAHolliday()
    {
        //bool hotelOK = await ReserveAHotel();//HTTP async request
        //bool flightOK = await ReserveAHotel();////HTTP async request
        var t1 = ReserveAHotel("FirstHotel");
        var t2 = ReserveAHotel("SecondHotel");
        await Task.WhenAll(t1, t2);
        bool result = t1.Result && t1.Result;// hotelOK && flightOK;
        return result;
    }
    public static async Task<bool> ReserveAHotel(string name)
    {
        Console.WriteLine("Reserve A Hotel started for "+ name);
        await Task.Delay(3000);
        if (name == "FirstHotel") 
            await Task.Delay(500); //delaying first hotel on purpose.
        Console.WriteLine("Reserve A Hotel done for " + name);
        return true;
    }
}
like image 76
Guy Avatar answered Oct 22 '22 00:10

Guy