Controlling the concurrency level using MaxDegreeOfParallelism in Parallel

Posted on


This is another nice available in the box feature when using the Parallel class, is the ability to basically limit the concurrency for the actions that we want to execute in parallel.

Why would we ever want to do this? wouldn’t it be best if we parallel some activities as many as possible?

For certain cases, we might want to be careful for not creating too many sudden requests at the same time, a good example will be if we’re triggering a long running process in our application server, you wouldn’t want to spawn too many requests at the same time to the server, as the server may not be able to handle so many requests at the same time and not surprisingly go down due to overload. This can be categorized as DOS attack, your back end guys will hate you for this, trust me :p

To set the concurrency level of the actions that you’re going to invoke with the Parallel class is pretty simple.

Parallel.Invoke(new ParallelOptions() { MaxDegreeOfParallelism = concurrencyLevel }, actions);

Find more about the MaxDegreeOfParallelism property in msdn.
We don’t have this such of property in the TaskCreationOptions that we can simply pass for Task, but there’s a LimitedConcurrencyLevelTaskScheduler nicely available which we can achieve the same result below where i basically spawn 10 processes with 2 max concurrency level.


15-Apr-2011 21:04:33.948 - Thead#13 - Creating 10 process definitions
15-Apr-2011 21:04:33.948 - Thead#13 - Start queueing and invoking all 10 processes
15-Apr-2011 21:04:33.948 - Thead#13 - Doing something here
15-Apr-2011 21:04:33.948 - Thead#14 - Doing something here
15-Apr-2011 21:04:34.964 - Thead#13 - Doing something here
15-Apr-2011 21:04:34.964 - Thead#14 - Doing something here
15-Apr-2011 21:04:35.964 - Thead#13 - Doing something here
15-Apr-2011 21:04:35.964 - Thead#14 - Doing something here
15-Apr-2011 21:04:36.964 - Thead#13 - Doing something here
15-Apr-2011 21:04:36.964 - Thead#14 - Doing something here
15-Apr-2011 21:04:37.964 - Thead#13 - Doing something here
15-Apr-2011 21:04:37.964 - Thead#14 - Doing something here
15-Apr-2011 21:04:38.964 - Thead#13 - All processes have been completed

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace ParallelTests
{
    [TestClass]
    public class TaskSchedulerConcurrencyTest
    {
        [TestMethod]
        public void TestMethod1()
        {
            var p = new ProcessorUsingParallel();
            p.DoProcess(processToCreate: 10, concurrencyLevel: 2);
        }
    }

    public class ProcessorUsingParallel
    {
        public void DoProcess(int processToCreate, int concurrencyLevel)
        {
            SetTurboMode();

            Debug("Creating {0} process definitions", processToCreate.ToString());

            var actions = new Action[processToCreate];
            for (int i = 0; i < processToCreate; i++)
            {
                actions[i] = () => DoSomething(1000);
            }

            Debug("Start queueing and invoking all {0} processes", processToCreate.ToString());
            var options = new ParallelOptions();
            options.MaxDegreeOfParallelism = concurrencyLevel;
            //options.TaskScheduler = new LimitedConcurrencyLevelTaskScheduler(concurrencyLevel); -- we can achieve the same result with this
            Parallel.Invoke(options, actions);

            Debug("All processes have been completed");
        }

        private void DoSomething(int Sleep)
        {
            Debug("Doing something here");
            Thread.Sleep(Sleep);
        }

        /// <summary>
        /// oh i just wish the framework would have this in place like Console.WriteLine
        /// </summary>
        /// <param name="format"></param>
        /// <param name="args"></param>
        private static void Debug(string format, params object[] args)
        {
            System.Diagnostics.Debug.WriteLine(
                string.Format("{0} - Thead#{1} - {2}",
                    DateTime.Now.ToString("dd-MMM-yyyy HH:mm:ss.fff"),
                    Thread.CurrentThread.ManagedThreadId.ToString(),
                    string.Format(format, args)));
        }
        /// <summary>
        /// This is not intended for production purpose
        /// </summary>
        private static void SetTurboMode()
        {
            int t, io;
            ThreadPool.GetMaxThreads(out t, out io);
            Debug("Default Max {0}, I/O: {1}", t, io);

            var success = ThreadPool.SetMinThreads(t, io);
            Debug("Successfully set Min {0}, I/O: {1}", t, io);
        }
    }
}

Advertisements

2 thoughts on “Controlling the concurrency level using MaxDegreeOfParallelism in Parallel

    […] Parallel data submission with limited concurrency With long running processes, we need to be careful not to overload the back end services, so when TPL comes with Limited Concurrency Task Scheduler, this becomes a life saver and we can remove all the previous code complexities to achieve the same. […]

    […] example Tagged: .NETcMultiThreadingquestions /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */ var disqus_shortname = 'dkphp'; // required: replace example with your forum shortname var disqus_identifier = "342183e2655bddda3bbbfbcb2bb984b5"; var disqus_url = "http://www.dkphp.com/questions-2/can-i-limit-the-amount-of-system-threading-tasks-task-objects-that-run-simultaneously.html&quot;; /* * * DON'T EDIT BELOW THIS LINE * * */ (function() { var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; dsq.src = 'http://&#039; + disqus_shortname + '.disqus.com/embed.js'; (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); })(); var infolink_pid = 1023613; var infolink_wsid = 1; […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s