Multi threading not working as expected with Parallel Foreach

Multi tool use
Multi tool use


Multi threading not working as expected with Parallel Foreach


public void GetTopRequest()
{
DataTable dtListofTransaction = new DataTable();
string sconnection = ConfigurationManager.AppSettings[ConfigurationManager.AppSettings["BUToProcess"].ToString()].ToString();
string query = "select Error_Counter, MembershipEnrollmentStatus_ID_PKID, outbound_xml, type_of_transaction, ProcessSet_GUID from MES where TP = 0 and RS = 'A' and type_of_transaction = 'Initial Enrollment'";

using (SqlConnection sqlConn = new SqlConnection(sconnection))
{
sqlConn.Open();

using (SqlCommand cmd = new SqlCommand(query, sqlConn))
{
dtListofTransaction.Load(cmd.ExecuteReader());
var tmpdtListofTransaction = dtListofTransaction;

if (dtListofTransaction.Rows.Count > 0)
{
var distinctListOfFamilies = (from row in tmpdtListofTransaction.AsEnumerable()
select row.Field<Guid>("ProcessSet_GUID")).Distinct().ToList();
int countOfFamilies = distinctListOfFamilies.Count();
int FamiliesToBeProcessedByThread = (countOfFamilies > 50 ? (countOfFamilies / Convert.ToInt32(ConfigurationManager.AppSettings["ThreadsToUse"])) + 1 : countOfFamilies);
var listOfSubscriberLists = splitList<Guid>(distinctListOfFamilies, FamiliesToBeProcessedByThread);
var tmplistOfSubscriberLists = listOfSubscriberLists;

if (countOfFamilies > 0)
{
Parallel.ForEach(listOfSubscriberLists,, new ParallelOptions { MaxDegreeOfParallelism = 4}, ac =>
{
foreach (var guid in ac)
{
Console.WriteLine(guid + " : " + DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss.fff"));
var dbMembersToProcess = tmpdtListofTransaction.AsEnumerable().Where(p => object.Equals(p["ProcessSet_GUID"], guid) && p["outbound_xml"] != null);

foreach (var member in dbMembersToProcess)
{
PushWWRequest.SendTransactions(member["outbound_xml"].ToString(), member["type_of_transaction"].ToString(), member["MembershipEnrollmentStatus_ID_PKID"].ToString(), Convert.ToInt32(member["Error_Counter"].ToString()));
}
}
});
}
}
}

sqlConn.Close();
}
}

public static void SendTransactions(string sRequest, string sTransactionType, string sPKID = "", int ErrorCounter = 0)
{
switch (sTransactionType)
{
case TransactionType.INITIALENROLLMENT:
try
{
CMInitialCustomerSetupTypeClient svcInitialCustomerSetupClientProxy = ClientOrmbProxy<CMInitialCustomerSetupTypeClient>();
CMInitialCustomerSetup initialCustomerSetupRequest = Deserialize<CMInitialCustomerSetup>(sRequest);
svcInitialCustomerSetupClientProxy.CMInitialCustomerSetup(initialCustomerSetupRequest);
}
catch (System.ServiceModel.CommunicationException svcExcpt)
{
print svcExcpt
}
break;
}
}



I am trying to send 4 requests using 4 threads (as defined with the degree of parallelism above set to 4) at a time to process using the above code in Parallel.ForEach loop, but I am not seeing 4 requests taken simultaneously and the threads are processed in random order. I am not sure what I am doing wrong here.


Parallel.ForEach



Any suggestions would be helpful...Thank you.





but I am not seeing 4 requests taken simultaneously and the threads are processed in random order please explain this more
– TheGeneral
Jun 30 at 3:17


but I am not seeing 4 requests taken simultaneously and the threads are processed in random order





I suggest you divide your code into many methods to maintain readability first.
– Rawitas Krungkaew
Jun 30 at 3:17





Expect the threads to be sent/completed in random order. It's threads after all. If you need something synchronized then do it after the Parallel.ForEach.
– ffhighwind
Jun 30 at 3:46




1 Answer
1



Since your question is fairly trivial, ill answer it with a bunch of other suggestions



You shouldn't be using Parallel.ForEach with IO bound tasks, you are wasting threads and resources, the async await pattern is a better approach, it will release threads back to the operating system when waiting for an IO completion port, I'd consider an ActionBlock for the best of both worlds.


Parallel.ForEach


async


await


ActionBlock



Your code is a mess (said in the nicest possible way)



MaxDegreeOfParallelism is only a suggestion and not a contract, TPL will decide what it needs and thinks appropriate.


MaxDegreeOfParallelism



If running in parallel, there is no guarantee on what will get executed in which order, that is the idea of parallel programming, threads have a degree of freedom and order is not guaranteed



You are creating reference copies all over the place, there is no need to do that i.e var tmpdtListofTransaction = dtListofTransaction;


var tmpdtListofTransaction = dtListofTransaction;



DataTable dtListofTransaction = new DataTable() should be in a using statment


DataTable dtListofTransaction = new DataTable()



Reduce your nesting for readability, just because you can put things into a lambda statement doesn't mean you should, make it easier for your self



Stop using the ConfigurationManager in nested statements, it makes it impossible to read, use expression bodied properties, or store them in a variable once and be done with it


ConfigurationManager



If you want to assure exactly 4 threads at once, consider makign them tasks and using WaitAll, or WhenAll depending what you want, probably await Task.WhenAll(tasks);


WaitAll


WhenAll


await Task.WhenAll(tasks);






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

xptkwcD0ze1uLQVLgckUHgnovVsYmMmV,hqqh6vcIic3aFf0i,5G33,RzRvHszIZ
e VVU5S7JrnCHKL9ZU5y,COsTxiQjAS2qtdP4,V1BqtvgseVTWmNDL9KXe,ga8,63KbIi4 zJuIDfV8 eI2bjFAdtkNhhKvm6 d,8

Popular posts from this blog

Delphi Android file open failure with API 26

.

Amasya