web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Dynamics 365 Community / Blogs / CRM TIPS By PRM / Parallel.For using in Dynam...

Parallel.For using in Dynamics 365–Improves the performance for Batch process

P. R. M Profile Picture P. R. M 739

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;
           }
       }


This was originally posted here.

Comments

*This post is locked for comments