3

Task.Run: Queues the specified work to run on the ThreadPool and returns a task or Task<TResult> handle for that work.

Parallel.Invoke: Executes each of the provided actions, possibly in parallel.

Effectively they spin up a new thread from the thread pool. So is Parallel.Invoke same as calling multiple Task.Runs?

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
variable
  • 8,262
  • 9
  • 95
  • 215
  • 1
    Does this answer your question? [Task.Factory.StartNew vs. Parallel.Invoke](https://stackoverflow.com/questions/14130929/task-factory-startnew-vs-parallel-invoke) – JHBonarius Jul 07 '22 at 06:28
  • @JHBonarius I would say that the [linked question](https://stackoverflow.com/questions/14130929/task-factory-startnew-vs-parallel-invoke), although thematically very similar, it's not an exact duplicate, because the `Task.Factory.StartNew` is not exactly the same with `Task.Run`. The `Task.Factory.StartNew` is considered a very specialized tool nowadays, so IMHO it should not be a prerequisite for someone interested in the differences berween `Parallel.Invoke` and `Task.Run` to first educated themselves in the differences between `Task.Factory.StartNew` and `Task.Run`. – Theodor Zoulias Jul 07 '22 at 06:43
  • @TheodorZoulias of course, but it's a question from 2013. And imho (I think it's even the guideline) you should tag duplicate as much as possible, to prevent fragmentation of information. An updated answer should be put there, if necessary – JHBonarius Jul 07 '22 at 06:58
  • @JHBonarius [the definition](https://meta.stackoverflow.com/a/417477/11178549) of duplicates is: *"Questions that have already been answered on this site. All closures should follow an apples-to-apples comparison. In other words, if the question matches exactly to one that has been previously asked, or if the question is closely related and there is an answer that would serve both questions"*. I don't think that I could post [my answer](https://stackoverflow.com/a/72893224/11178549) to the other question. It would be off-topic there. – Theodor Zoulias Jul 07 '22 at 07:10

1 Answers1

3

So you want to compare these two techniques:

Parallel.Invoke(source.Select(source => () => ProcessItem(source)).ToArray());
Task.WaitAll(source.Select(source => Task.Run(() => ProcessItem(source))).ToArray());

There is one similarity and two differences. The similarity is that in both cases all actions will be invoked and completed before the Parallel.Invoke/Task.WaitAll returns. It doesn't matter if some of the actions fail. There is no support for a fail-fast strategy.

The two differences are:

  1. The Parallel.Invoke uses the current thread as one of the worker threads. On the contrary the Task.WaitAll+Task.Run uses exclusively ThreadPool threads. While the worker threads are working, the current thread is blocked doing nothing.

  2. The Parallel.Invoke can be configured with a specific MaxDegreeOfParallelism, TaskScheduler and CancellationToken (ParallelOptions). This is not possible with the Task.Run. It is possible with the Task.Factory.StartNew, but comparatively it's quite cumbersome.

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
  • You should mention the `await Task.WhenAll` option, where you also unblock the current thread – JHBonarius Jul 07 '22 at 07:01
  • `The Parallel.Invoke uses the current thread as one of the worker threads.` - plus more thread from the threadpool right? – variable Jul 07 '22 at 07:02
  • @variable yes, exactly. By default the other threads are from the `ThreadPool`. – Theodor Zoulias Jul 07 '22 at 07:20
  • @JHBonarius in that case I should also mention that the `Parallel.Invoke` can be offloaded to the `ThreadPool` with `await Task.Run(() => Parallel.Invoke(/*...*/))`. I preferred to keep it simple, since the OP has made no reference to asynchrony in the body of the question, or in the tags. – Theodor Zoulias Jul 07 '22 at 07:24