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:
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.
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.