Alex Rivera | Logout

How do you use AsParallel with the async and await keywords?

Asked 2012-09-24T11:47:44.080
27

I was looking at someone sample code for async and noticed a few issues with the way it was implemented. Whilst looking at the code I wondered if it would be more efficient to loop through a list using as parallel, rather than just looping through the list normally.

As far as I can tell there is very little difference in performance, both use up every processor, and both talk around the same amount of time to completed.

This is the first way of doing it

var tasks= Client.GetClients().Select(async p => await p.Initialize());

And this is the second

var tasks = Client.GetClients().AsParallel().Select(async p => await p.Initialize());

Am I correct in assuming there is no difference between the two?

The full program can be found below

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            RunCode1();
            Console.WriteLine("Here");
            Console.ReadLine();

            RunCode2();
            Console.WriteLine("Here");

            Console.ReadLine();

        }

        private async static void RunCode1()
        {
            Stopwatch myStopWatch = new Stopwatch();
            myStopWatch.Start();

            var tasks= Client.GetClients().Select(async p => await p.Initialize());

            Task.WaitAll(tasks.ToArray());
            Console.WriteLine("Time ellapsed(ms): " + myStopWatch.ElapsedMilliseconds);
            myStopWatch.Stop();
        }
        private async static void RunCode2()
        {
            Stopwatch myStopWatch = new Stopwatch();
            myStopWatch.Start();
            var tasks = Client.GetClients().AsParallel().Select(async p => await p.Initialize());
            Task.WaitAll(tasks.ToArray());
 
Edit
Report

1 Answer

7

There's a singular major difference.

In the following code, you are taking it upon yourself to perform the partitioning. In other words, you're creating one Task object per item from the IEnumerable<T> that is returned from the call to GetClients():

var tasks= Client.GetClients().Select(async p => await p.Initialize());

In the second, the call to AsParallel is internally going to use Task instances to execute partitions of the IEnumerable<T> and you're going to have the initial Task that is returned from the lambda async p => await p.Initialize():

var tasks = Client.GetClients().AsParallel().
    Select(async p => await p.Initialize());

Finally, you're not really doing anything by using async/await here. Granted, the compiler might optimize this out, but you're just waiting on a method that returns a Task and then returning a continuation that does nothing back through the lambda. That said, since the call to Initialize is already returning a Task, it's best to keep it simple and just do:

var tasks = Client.GetClients().Select(p => p.Initialize());

Which will return the sequence of Task instances for you.

answered 2012-09-24T12:22:08.560

Your Answer