El-tayeb Karrar
El-tayeb Karrar

Reputation: 41

Async And Await in C# And problems

This program does not print the output in the correct order.

public static void Main(string[] args)
    {
        new Program().Start();
    }

    public async void Start()
    {
        int num1 = await GetNumber();
        int num2 = await GetNumber();
        int num3 = await GetNumber();
        Console.WriteLine("Wait...");
        Console.ReadKey();
    }

    public static async Task<int> GetNumber()
    {
        System.Threading.Thread.Sleep(4000);
        Console.WriteLine("Hello");
        return 0;
    }

It outputs:

--------wait 4Seconds
--------print Hello
--------wait 4Seconds
--------print Hello
--------wait 4Seconds
--------print Hello
--------print wait....

It should output

--------print wait....
--------wait 4Seconds
--------print Hello
--------print Hello
--------print Hello

Upvotes: 1

Views: 2682

Answers (2)

bradgonesurfing
bradgonesurfing

Reputation: 32162

Use

Await Task.Delay(Timespan.FromMilliSeconds (4000))

instead of Thread.Sleep.

The fully worked out example.

using System;
using System.Threading.Tasks;

namespace Brad
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var task = new Program().Start();
            Console.WriteLine("Wait...");
            // You have to put a synchronous Wait() here because
            // Main cannot be declared as async
            task.Wait();
        }

        public async Task Start()
        {
            int num1 = await GetNumber();
            int num2 = await GetNumber();
            int num3 = await GetNumber();
            Console.WriteLine("Finished");
        }

        public static async Task<int> GetNumber()
        {
            await Task.Delay(TimeSpan.FromMilliseconds(400));
            Console.WriteLine("Hello");
            return 0;
        }
    }
}

You can see it running here

https://dotnetfiddle.net/KHJaDZ

or maybe you wanted the tasks running in parallel instead of one after the other. You can try

using System;
using System.Threading.Tasks;

namespace Brad
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var task = new Program().Start();
            Console.WriteLine("Wait...");
            // You have to put a synchronous Wait() here because
            // Main cannot be declared as async
            task.Wait();
        }

        public async Task Start()
        {
            var task1 = GetNumber();
            var task2 = GetNumber();
            var task3 = GetNumber();
            // This runs the tasks in parallel
            await Task.WhenAll(task1, task2, task3);
            Console.WriteLine("Finished");
        }

        public static async Task<int> GetNumber()
        {
            await Task.Delay(TimeSpan.FromMilliseconds(400));
            Console.WriteLine("Hello");
            return 0;
        }
    }
}

and this is running here.

https://dotnetfiddle.net/kVk77Z

Upvotes: 9

Dave Cousineau
Dave Cousineau

Reputation: 13148

await means "break the method in half here and come back later when this call finishes". It's how you "convert" a Task<T> into a T: by waiting for (awaiting) the task. Otherwise you are stuck with a Task<T>.

It seems like what you are looking for instead is not awaiting the tasks so that they run asynchronously, but if you did that then you wouldn't be able to get the int results.

(As the other answer mentions, you also need to await something in GetNumber or it will not actually be asynchronous.)

Something like:

public static void Main(string[] args) {
    new Program().Start();
}

public void Start() {
    GetNumber();
    GetNumber();
    GetNumber();
    Console.WriteLine("Wait...");
    Console.ReadKey();
}

public static async Task<int> GetNumber() {
    await Task.Delay(TimeSpan.FromSeconds(1));
    Console.WriteLine("Hello");
    return 0;
}

should give the output you expect:

Wait...
Hello
Hello
Hello

Upvotes: 2

Related Questions