I am confused why Actions have parameters if you are fine with their execution without sending parameter values. It is probably best to use Parallel.ForEach with default values:
Action<string, int, double, double>[] actions;
Parallel.ForEach(actions, action => action(string.Empty, 0, 0, 0));
If you want to send parameters, replace the values as you wish.
I used the following steps for my tests:
Parallel.For(0, actions.Length, index => actions[index] = (s, i, d1, d2) => Thread.Sleep(100));
Parallel.For(0, parameterless.Length, index => parameterless[index] = () => Thread.Sleep(100));
20 :
.Invoke: 0.3000709
.ForEach: 0.3022143
: 2.0000706
, Parallel.Invoke , , .
, , Parallel.ForEach, , Parallel.Invoke 0.300979 .