Converting Parallel ForEach into PLINQ to process list of Tasks

174 views Asked by At

I am trying to load as many messages into a server fast as possible. I currently have this bit of code and to load 50000 messages to a MessagingServer it takes around 5 minutes. This is a list of tasks that have server name, queuename and the message to place on the queue.

  taskList.Add(new Task(() => PlaceMessageOnQueue(server, queueName, message)));

This is the current code that I have but I want to convert this to PLINQ as hopes to make this even faster.

_= Parallel.ForEach(task, new ParallelOptions()
{
MaxDegreeOfParallelism = Environment.ProcessorCount; //I have 4 Cores
},t => {
 t.Start();
 t.Wait();
Console.WriteLine(t.Status)
});

What I have so far but this isn't starting the tasks. This is the code below that I need help with.

var results = task.
.AsParallel()
.AsOrdered()
.WithDegreeofParallelism(Environment.ProcessorCount)
.ToList();
1

There are 1 answers

2
Eric J. On

You can approach this by consuming the messages in parallel and selecting the result of processing the message, as in this example:

static void Main(string[] args)
{
    var messages = Enumerable.Range(0, 10).Select(i => $"Message {i}");

    var results = messages
        .AsParallel()
        .AsOrdered()
        .WithDegreeOfParallelism(Environment.ProcessorCount)
        .Select(m => PlaceMessageOnQueue("FOO", "BAR", m))
        .ToList();
}
static bool PlaceMessageOnQueue(string server, string queue, string message)
{
    Console.WriteLine($"Starting {server}/{queue}/{message}");
    Thread.Sleep(1000);
    Console.WriteLine($"Finished {server}/{queue}/{message}");

    return true; // E.g. representing success
}

Note there isn't a reason to believe this will be fundamentally faster than your last approach. You may wish to look at a producer/consumer pattern using Channels. In many use cases, channels outperform similar concurrency options in .NET.