Steve
Steve

Reputation: 4563

Unable to add Parallelism Task

How do I add task parallelism for this code? I have added in several places but it is not running as expected.

class Program
{
    static void Main(string[] args)
    {
        Task.Run(() =>PizzaTask());
    }

    static async void PizzaTask()
    {
        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();
        int totalPizza = 10;
        Console.WriteLine($"Started preparing {totalPizza} pizza");
        for (var x = 1; x <= totalPizza; x++)
        {
            //Task.Run(() => MakePizza(x));
            await MakePizza(x);
        }
        stopwatch.Stop();

        Console.WriteLine($"Finished preparing {totalPizza} pizza");
        Console.WriteLine("Elapsed time: " + stopwatch.Elapsed.TotalSeconds);

    }

    static async Task MakePizza(int n)
    {
        PreparePizza(n);
        await BakePizza(n);
    }

    static void PreparePizza(int n)
    {
        Console.WriteLine("Start preparing pizza " + n);
        Thread.Sleep(5000);// synchronous
        Console.WriteLine("Finished preparing pizza " + n);
    }

    static async Task BakePizza(int n)
    {
        Console.WriteLine("Start baking pizza " + n);
        await Task.Delay(15000); // asynchronous 
        //Thread.Sleep(15000); // synchronous 
        Console.WriteLine("Finished baking pizza " + n);
    }
}

The working version before this is in BakePizza, I set to async await. But if I set async await for PizzaTask(), it doesn't work.

Upvotes: 0

Views: 51

Answers (1)

user1672994
user1672994

Reputation: 10849

I've changed the code to make it async using Parallel loop via var tasks = Enumerable.Range(0, totalPizza).Select(i => MakePizza(i));

  • The below code invoke the MakePizza parallelly instead of sequentially via for (var x = 1; x <= totalPizza; x++) { //Task.Run(() => MakePizza(x)); await MakePizza(x); }

  • Used Task.Delay instead of Thread.Sleep to make sure the current thread is not blocked.

  • Change the Code from async void to aysnc Task. The async+void combination can crash the system and usually should be used only on the UI side event handlers.
  • As mentioned by @Steve, use ConfigureAwait(false) to return to any available thread instead of forcing context to return the caller thread.

Updated Code:

public class Program
{
    public static void Main()
    {
       PizzaTask().GetAwaiter().GetResult();
    }

    static async Task PizzaTask()
    {
        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();
        int totalPizza = 10;
        Console.WriteLine("Started preparing " + totalPizza + "  pizza");

        var tasks = Enumerable.Range(0, totalPizza).Select(i => MakePizza(i));
        await Task.WhenAll(tasks).ConfigureAwait(false);

        stopwatch.Stop();

        Console.WriteLine("Finished preparing " + totalPizza + "  pizza");
        Console.WriteLine("Elapsed time: " + stopwatch.Elapsed.TotalSeconds);

    }

    static async Task MakePizza(int n)
    {
        await PreparePizza(n).ConfigureAwait(false);
        await BakePizza(n).ConfigureAwait(false);
    }

    static async Task PreparePizza(int n)
    {
        Console.WriteLine("Start preparing pizza " + n);
        await Task.Delay(5000);
        //Thread.Sleep(5000);// synchronous
        Console.WriteLine("Finished preparing pizza " + n);
    }

    static async Task BakePizza(int n)
    {
        Console.WriteLine("Start baking pizza " + n);
        await Task.Delay(15000); // asynchronous 
        //Thread.Sleep(15000); // synchronous 
        Console.WriteLine("Finished baking pizza " + n);
    }
}

You can check the output of code in dotnetfiddle -- https://dotnetfiddle.net/HepavC

Upvotes: 3

Related Questions