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?
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.
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)));
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With