I'm calling a slow webservice in parallel. Things were great until I realized I need to get some information back from the service. But I don't see where to get the values back. I can't write to the database, HttpContext.Current appears to be null inside of a method called using Parallel.ForEach
Below is a sample program (in your mind, please imagine a slow web service instead of a string concatenation)
using System;
using System.Threading.Tasks;
class Program
{
static void Main(string[] args)
{
WordMaker m = new WordMaker();
m.MakeIt();
}
public class WordMaker
{
public void MakeIt()
{
string[] words = { "ack", "ook" };
ParallelLoopResult result = Parallel.ForEach(words, word => AddB(word));
Console.WriteLine("Where did my results go?");
Console.ReadKey();
}
public string AddB(string word)
{
return "b" + word;
}
}
}
You've discarded it in here.
You probably want something like,
If you want some sort of collection at the end of this, consider using one of the collections under
System.Collections.Concurrent
, likeConcurrentBag
Do not use
ConcurrentBag
to collect results as it is extremely slow. Use local lock instead.How about something like this:
I believe the locking or concurrent objects isn't necessary unless you need the results to interact with one another (like you were computing a sum or combining all the words). In this case ForEach neatly breaks your original list up and hands each thread its own object that it can manipulate all it wants without worrying about interfering with the other threads.
This seems safe, fast, and simple:
Your may consider using
AsParallel
extension method ofIEnumerable
, it will take care of the concurrency for you and collect the results.words.AsParallel().Select(AddB).ToArray()
Synchronisation (e.g. locks or concurrent collections that use locks) are usually bottleneck of concurrent algorithms. The best is to avoid synchronisation as much as possible. I am guessing that
AsParallel
uses something smarter like putting all the items produced on single thread into a local non-concurrent collection and then combining these at the end.