Nair
Nair

Reputation: 7458

Parallel.Invoke vs Task why exceution time different?

I have a queue which have like 144 items in it. Each queue element is a request. I am trying to increase the performance of the processing by trying to run the code in parallel. I call performaction(request) method. Which instantiate an object and pass the request to it and perform an action. I can run this action parallely since these requests are independent and the action results of the requests are also independent of each other. First I tried

foreach(var request in queue.Values)
    Parallel.Invoke(() =>PerformAction(request);

then I tried for the same foreach.

var task = new Task(() => PerformAction(request));
task.Start();

and outside the foreach I have

Task.WaitAll();

When the run the program the parallel.invoke took almost 3 second to complete while Task took almost 0.005s to complete.

I have the following questions:

  1. Why parallel invoke took more time than the Task? It seems the parallel invoke did not run in parallel mode as I wanted.
  2. When I am using Task, for every request I am creating a new Task, what if I have a request of 1000 request, will I endup creating 1000 threads or CPU will take care of creating threads as required?
  3. Task.WaitAll() out side will it wait for all the tasks to complete before the program terminates?

Upvotes: 2

Views: 3871

Answers (1)

yamen
yamen

Reputation: 15618

The problem in your code is that Task.WaitAll() doesn't work as you intended. You've saved and started a task:

var task = new Task(() => PerformAction(request));
task.Start();

But you haven't kept a reference to each task to pass to WaitAll. You're meant to save all the tasks in an array and then pass that array to WaitAll. So your program executes 'fast' with Tasks because it's not waiting to finish.

Your questions:

  1. See above for why Parallel.Invoke took more time - because it actually run. However, you're also not using it correctly. Parallel.Invoke takes an array of actions (Actions[]) and tries to run them all in parallel. You're calling it multiple times with a single action each time. I'm not even sure how your code compiles. I believe what you want is:

    Parallel.ForEach(queue.Values, request => PerformAction(request))
    
  2. You are creating a new task for each request, but that doesn't map one to one with a thread. By default, tasks use the thread pool.

  3. Task.WaitAll(tasks) does wait for all tasks to finish. But it doesn't if you don't pass it anything. Again, this shouldn't compile as you have it.

Upvotes: 9

Related Questions