Alex Alex - 3 months ago 9
C# Question

Asynchronously invoking a parallel for loop

I would like to do something like this:

public async Task MyMethod()
{
// Do some preparation

await Parallel.ForEachAsync(0, count, i => { // Do some work //});

// do some finalization
}


However, I did not find an elegant way of doing so. I thought of two ways, but they are sub-optimal:


  1. The only thing I thought about is manually partitioning the range, creating tasks, and then using Task.WhenAll.

  2. Using the following code
    Task.Factory.StartNew(() => Parallel.For(...));
    .

    The problem is that it "wastes" a thread on the asynchronous task.

  3. Using TPL Dataflow's ActionBlock, and posting the integers one by one. The drawback is that it does not partition the range in a smart way like Parallel.For does, and works on each iteration one by one.

  4. Manually using a Partitioner with Partitioner.Create, but it is less elegant. I want the framework to do intelligent partitioning for me.


Answer

You have a regular synchronous parallel loop that you'd like to invoke asynchronously (presumably to move it off the UI thread).

You can do this the same way you'd move any other CPU-bound work off the UI thread: using Task.Run:

public async Task MyMethod()
{
  // Do some preparation

  await Task.Run(() => Parallel.ForEach(0, count, i => { /* Do some work */ }));

  // do some finalization
}

There is no thread "wasted" because Parallel.ForEach will use the calling thread as one of its worker threads.

(This is recipe 7.4 "Async Wrappers for Parallel Code" in my book).

Comments