Parallel.For using in Dynamics 365–Improves the performance for Batch process
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.

Like
Report
*This post is locked for comments