Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a task inside a foreach loop

Tags:

c#

I have a typical foreach loop that calls a method where the parameter is an element of the collection we're looping over; something like this:

foreach (byte x in SomeCollection)
{
   SomeMethod(x);
}

The problem is that SomeMethod takes a long time to run. I want to move the call into a new task so that the loop just creates the tasks and then the thread that called the loops just continues. How do I do this in a thread-safe way?

Edit

I had a performance issue because SomeMethod makes several DB calls. So I converted the loop to a Parallel.ForEach but that didn't make much of a difference because each thread then call the DB. What I'm looking to do is just create Tasks that will run in the background and let the main thread continue.

like image 870
frenchie Avatar asked Aug 05 '14 19:08

frenchie


3 Answers

One way would be to use Parallel.ForEach to do this:

Parallel.ForEach(SomeCollection, x => SomeMethod(x));

The code would wait for all calls of SomeMethod to complete before proceeding, but the individual calls may run in parallel.

If you don't want to wait for the calls to finish, wrap this call in StartNew:

Task.Factory.StartNew(() => Parallel.ForEach(SomeCollection, x => SomeMethod(x)));
like image 63
Sergey Kalinichenko Avatar answered Oct 10 '22 17:10

Sergey Kalinichenko


What thread safety do you expect? This will be thread-safe:

foreach (byte x in SomeCollection) { Task.Factory.StartNew(() => SomeMethod(x)); }

until your method does not modify any shared state, which isn't thread-safe itself.

like image 45
Dennis Avatar answered Oct 10 '22 16:10

Dennis


You could something like:

IEnumerable<Task> doWork()
{
  foreach(var x in SomeCollection)
    yield return Task.Run(()=>SomeMethod(x);
}

Task.WhenAll(doWork());

This will run them all at the same time.

like image 43
poy Avatar answered Oct 10 '22 15:10

poy