I took the idea from this web page. In this article a number of experiments were run to find the optimum way to run a Producer-Consumer using the TPL.
// This calculates distances between a target system and a bunch of other systems
// Results are returned as a dictionary of a system id to a double where the double
// represents the distance from the given system to the target system
public IDictionary<int, double> CalcSystemDistances(
int targSystemId,
ISet<int> systemIds)
{
var idToDistanceMap = new ConcurrentDictionary<int, double>();
// _systemDb is a repository of systems
var targSystem = _systemDb.Get(targSystemId);
if (targSystem != null)
{
int WorkerCount = Math.Max(Environment.ProcessorCount - 2, 4);
// Setup the queue
var blockingCollection = new BlockingCollection<SystemInfo>();
// Declare the worker - Calculates a distance
Action<SystemInfo> work = eddbSys =>
{
double dist = targSystem.Location.DistanceTo(eddbSys.Location);
idToDistanceMap.TryAdd(eddbSys.Id, dist);
};
// Begin producing source data
Task.Run(() =>
{
foreach (var eddbSys in _systemDb.Get(systemIds).Where(s => s != null))
{
blockingCollection.Add(eddbSys);
}
blockingCollection.CompleteAdding();
});
// Start consuming
blockingCollection.
GetConsumingEnumerable().
AsParallel().
WithDegreeOfParallelism(WorkerCount).
WithMergeOptions(ParallelMergeOptions.NotBuffered).
ForAll(work);
}
return idToDistanceMap;
}
No comments:
Post a Comment