I have come across Parallel.For / Parallel.Foreach while working on one of the Performance Related issue. I have done POC and its giving 2 times better performance in my local machine. [We could get better than this results if we have more than one CPUs. Its depending on # of CPUs].

We could implement when we need to Bulk data processing through batch jobs (SSIS or Console apps).

Lets start with POC Details:

1. I have done POC on Account entity to create 5K records. Normal Creation takes 412 Sec and Parallel For takes 212 Sec.

2. Create new service for each Parallel Thread by using Thread ID

Sample Code:

public static void fn_ParallelFor()
       {          
           IOrganizationService service = null;

          // Start the timer to see how long this takes
           Stopwatch watch = new Stopwatch();
           watch.Start();

          // Test different Parallelism options
           ParallelOptions ops = new ParallelOptions();
           ops.MaxDegreeOfParallelism = 2;

          // This loop uses the new multi-threaded extensions
           Parallel.For(0, 5000, i =>
           {
               try
               {                  
                   // Creating one service per thread
                   IOrganizationService theService = GetCRMService(Thread.CurrentThread.ManagedThreadId);

                  Entity acc = GetDefaultAccount(i, Thread.CurrentThread.ManagedThreadId);

                  Guid id = theService.Create(acc);

                  // Write out our progress
                   Console.WriteLine(id.ToString(“b”) + ” ” + i + ” ” + watch.ElapsedMilliseconds);              
               }
               catch (Exception ex)
               {
                   Console.WriteLine(ex.Message);
               }               

          }); // Parallel.For

          watch.Stop();

          // How long did all that take?
           Console.WriteLine(watch.ElapsedMilliseconds);
           Console.ReadLine();
       }

     
       static Entity GetDefaultAccount(int i, int ThreadId)
       {
           Entity acc = new Entity(“account”);
           acc[“name”] = “Test Account” + i.ToString()  + ” Threadid: ” + ThreadId.ToString();
           acc[“numberofemployees”] = i;
           acc[“websiteurl”] = “http://prasad.test.com”;
           return acc;
       }     

      static Dictionary<int, IOrganizationService> _crmOrgServices = new Dictionary<int, IOrganizationService>();

      public static IOrganizationService GetCRMService(int ThreadID)
       {
           IOrganizationService _currentService;

          // Was a service already created for this thread ID?
           if (_crmOrgServices.TryGetValue(ThreadID, out _currentService))
           {
               return _currentService;
           }
           else
           {
               string url = (ConfigurationManager.AppSettings[“url”] != null) ? ConfigurationManager.AppSettings[“url”] : string.Empty;
               string DefaultCredential = (ConfigurationManager.AppSettings[“DefaultCredential”] != null) ? ConfigurationManager.AppSettings[“DefaultCredential”] : string.Empty;
               string domain = (ConfigurationManager.AppSettings[“domain”] != null) ? ConfigurationManager.AppSettings[“domain”] : string.Empty;
               string username = (ConfigurationManager.AppSettings[“username”] != null) ? ConfigurationManager.AppSettings[“username”] : string.Empty;
               string password = (ConfigurationManager.AppSettings[“password”] != null) ? ConfigurationManager.AppSettings[“password”] : string.Empty;
               url += “/XRMServices/2011/Organization.svc”;

              ClientCredentials credentials = new ClientCredentials();

              if (DefaultCredential.Equals(“1”))
               {
                   credentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
               }

              else if (DefaultCredential.Equals(“0”))
               {
                   if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(domain))
                   {
                       throw new Exception(“Error: Non-default connection requires username, password and domain!”);
                   }
                   else if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password) && !string.IsNullOrEmpty(domain))
                   {
                       credentials.Windows.ClientCredential = new System.Net.NetworkCredential(username, password);
                   }
               }

               if (!string.IsNullOrEmpty(url) && url.Contains(“https”))
               {
                   ServicePointManager.ServerCertificateValidationCallback = delegate (object s, X509Certificate certificate, X509Chain chain,
                   SslPolicyErrors sslPolicyErrors) { return true; };
               }
               ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
               OrganizationServiceProxy orgService = new OrganizationServiceProxy(new Uri(url), null, credentials, null);
               orgService.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior());
               _currentService = (IOrganizationService)orgService;

              // Dictionary Objects aren’t thread safe
               lock (((ICollection)_crmOrgServices).SyncRoot)
               {
                   // Cache the instance for this thread ID
                   _crmOrgServices.Add(ThreadID, _currentService);
               }
              
               return _currentService;
           }
       }