Parallel.Invoke() without waiting on execution to finish

13,675

Solution 1

If you want to wait for a piece of code to finish executing, instead of using Parallel.Invoke, why not just call the code directly?

Well normally you'd call Parallel.Invoke with multiple pieces of work. If you execute those pieces of work in series, it'll (probably) take longer than executing them in parallel.

"Execute in parallel" isn't the same as "execute in the background" - you appear to be looking for the latter, but that's not what Parallel.Invoke is about.

If you just want to start tasks, use Task.Run (or Task.Factory.StartNew prior to .NET 4.5). Parallel.Invoke is specifically for executing a bunch of actions in parallel, but then waiting for those parallel actions to complete.

As a concrete example, you can perform a sort by partitioning, then recursively sorting both sides of the pivot in parallel. Doing this will make use of multiple cores, but you would usually still want to wait until that whole sort had completed before you proceed.

Solution 2

Simply wrap your Parallel.Invoke call in a Task if you don't want to wait for completion.

Task.Factory.StartNew( () =>
    {
        Parallel.Invoke( <one or more actions> );
    } );

Solution 3

Are you looking for something like this?

async Task ParallelInvokeAsync(Action[] actions)
{
    var tasks = actions.Select(a => Task.Run(a));
    await Task.WhenAll(tasks);
}

Background execution:

ParallelInvokeAsync(actions); 
MessageBox.Show("I'm working");

Background execution with blocking, very similar to Parallel.Invoke:

ParallelInvokeAsync(actions).Wait(); 
MessageBox.Show("I'm dome working");
Share:
13,675
Anshul
Author by

Anshul

ASP.NET Developer by profession. Technologist by hobby. I love delving into software and hardware technologies to come up with solutions for the community, myself included.

Updated on June 05, 2022

Comments

  • Anshul
    Anshul almost 2 years

    Please know that I'm aware that Parallel.Invoke() is meant for task synchronization. My question is this:

    Is there a way to call an anonymous method using something like Parallel.Invoke in which the call does NOT wait on the execution to finish?

    I thought the whole point of parallel execution (or parallel invokation) is to NOT have to wait for the task to finish. If you want to wait for a piece of code to finish executing, instead of using Parallel.Invoke, why not just call the code directly? I guess I just don't understand the point of Parallel.Invoke. The documentation just says what it does, but doesn't mention any use-cases when this would be more useful than just calling the code directly.

  • Anshul
    Anshul about 10 years
    You're right, I was under the impression that executing in parallel is the same as executing in background. Can you tell me what the difference is and how it applies to Parallel.Invoke? Or point me to a resource that can help me understand the difference?
  • Jon Skeet
    Jon Skeet about 10 years
    @Anshul: Executing in parallel is simply using multiple cores to accomplish a goal. That can be done in a "fire and forget" way, but it's not always. See my edit for a concrete example of when it's useful to parallelize work without making it a background task.
  • Anshul
    Anshul about 10 years
    If I have 2 Parallel.Invokes in sequeunce, wouldn't the 2nd one wait until the first one is finished to be called? In that case, how would you execute the multiple pieces of code in parallel using Parallel.Invoke?
  • L.B
    L.B about 10 years
    @Anshul Parallel.Invoke(action1,action2); both actions will run in parallel but Parallel.Invoke will wait both of them to finish. Suppose their execution times are t1 and t2. Parallel.Invoke will wait max(t1,t2)seconds.
  • Anshul
    Anshul about 10 years
    What if I was to do Task.Factory.StartNew(()=>{//do whatever}); instead of using Parallel.Invoke? Wouldn't it have the same effect since you're starting a new task essentially?
  • Moho
    Moho about 10 years
    Sure, you would need to start a new task for each action you wish to execute in parallel, though.
  • Anshul
    Anshul about 10 years
    Understood. Seems like I was misunderstanding the reason behind Parallel.Invoke().
  • Moho
    Moho about 10 years
    If you're simply looking to execute an action on a background thread, create a task for that action. Parallel.Invoke is if you want to execute multiple actions 'simultaneously'
  • Moho
    Moho about 10 years
    and then synchronize after their execution completes
  • Anshul
    Anshul about 10 years
    @L.B That makes sense now. I just had the wrong idea in my head about what Parallel.Invoke is supposed to do.
  • Anshul
    Anshul about 10 years
    I suppose that would work as well. I just needed something that makes use of the TPL and executes a piece of code in parallel with the current line of execution. By that I mean that the current line of execution should not wait on the parallelized task to finish. Task.Factor.StartNew(()=>{}) satisfies this requirement. I wanted to keep the call succint mainly.
  • Anshul
    Anshul about 10 years
    @JonSkeet Task.Run is essentially what I was looking for. Thank you.
  • noseratio
    noseratio about 10 years
    @Anshul, how you use it depends on the caller. I updated the answer to illustrate it. Theoretically, Task.Factory.StartNew(() => Parallel.Invoke(actions)) would create one more thread than the ParallelInvokeAsync(actions) above.
  • Microsoft Developer
    Microsoft Developer over 9 years
    Best not to use StartNew use Task.Run! I see this mistake all the time.
  • Gil Sand
    Gil Sand about 8 years
    Hey @JonSkeet, is there a way to execute code when the last parallel task has finished ? Right now i have several async () => await Foo(); in the Parallel.Invoke, and I can't seem to find the sweet spot. It either takes the additive complete time of each consecutive call, or less than a second and clearly skips the waiting.
  • Jon Skeet
    Jon Skeet about 8 years
    @Zil: It sounds like you should ask a new question. It's slightly unusual (IMO) to use Parallel.Invoke and async/await at the same time...
  • Gil Sand
    Gil Sand about 8 years
    You're right. I'm confused, i'll write a specific question :)