Nick_F
Nick_F

Reputation: 1121

Using non-blocking tasks

The following code returns the incorrect product. I expect that I need to use the await term in my AsyncMultiply function and I tried adding it in front of all lines, but it didn't work. How can I fix the code so that the task becomes a non-blocking, correctly calculating task?

using System;
using System.Threading;
using System.Threading.Tasks;

namespace NonBlockingTasks
{
    class Program
    {
        static int prod;
        public static void Main(string[] args)
        {
            Task.Run(async () => { await AsyncMultiply(2, 3); });

            for(int i = 0; i < 10; i++) {
                Console.Write(i + " ");
                Thread.Sleep(100);
            }

            Console.WriteLine();
            Console.WriteLine("Prod = " + prod);

            Console.Write("Press any key to continue . . . ");
            Console.ReadKey();
        }

        public static async Task DoSomethingAsync()
        {
          await Task.Delay(100);
        }           

        public static async Task<int> AsyncMultiply(int a, int b)
        {
            Thread.Sleep(2000);
            prod = a * b;
            return prod;
        }
    }
}

Upvotes: 1

Views: 2068

Answers (1)

Alchemy
Alchemy

Reputation: 445

Task.Run returns a Task and you are not waiting for it to finish. If you are using C# 7.1 (.net 4.7) or greater you can surface the awaitable all the way to the caller:

        static int prod;
        public static async Task Main(string[] args)
        {
            Task running  = Task.Run(async () => { await AsyncMultiply(2, 3); });

            for (int i = 0; i < 10; i++)
            {
                Console.Write(i + " ");
                Thread.Sleep(100);
            }

            await running; // Wait for the previously abandoned task to run.


            Console.WriteLine();
            Console.WriteLine("Prod = " + prod);

            Console.Write("Press any key to continue . . . ");
            Console.ReadKey();
        }

        public static async Task DoSomethingAsync()
        {
            await Task.Delay(100);
        }

        public static async Task<int> AsyncMultiply(int a, int b)
        {
            Thread.Sleep(2000);
            prod = a * b;
            return prod;
        }

Otherwise, you can freeze the current thread, waiting for the task to complete:

        static int prod;
        public static void Main(string[] args)
        {
            Task running  = Task.Run(async () => { await AsyncMultiply(2, 3); });

            for (int i = 0; i < 10; i++)
            {
                Console.Write(i + " ");
                Thread.Sleep(100);
            }

            running.Wait(); // Freeze thread and wait for task.


            Console.WriteLine();
            Console.WriteLine("Prod = " + prod);

            Console.Write("Press any key to continue . . . ");
            Console.ReadKey();
        }

        public static async Task DoSomethingAsync()
        {
            await Task.Delay(100);
        }

        public static async Task<int> AsyncMultiply(int a, int b)
        {
            Thread.Sleep(2000);
            prod = a * b;
            return prod;
        }

Upvotes: 2

Related Questions