Creating manual threads - but getting duplicate threads

不羁岁月 提交于 2019-12-02 08:08:56

问题


ISSUE: Getting duplicate items, i.e more threads are getting created than the array size... Hi Folks, I am creating thread in the loop for each element of array. The real use is that the of sending a batch of messages using amazon ses. the messages are stored in the messageamazonRequestBatch and the loop runs through the batch and sends the messages.

HERE IS THE CODE:

Thread thrdSendEmail;
            try
            {
                string amazonMessageID = string.Empty;
                List<Thread> lstThread = new List<Thread>();
                foreach (int n in arrMessageid)
                {
                    thrdSendEmail = new Thread(() =>
                    {
                            try
                            {
                                amazonMessageID = SendSimpleEmail_Part2(messageAmazonRequestBatch.ElementAt(n).req);
                                messageAmazonRequestBatch.ElementAt(n).msg.AmazonMessageID = amazonMessageID;
                                logManager_MessageLogwithAmazonmsgID.LogMessage(",\t" + n , true);
                                //logManager_MessageLogwithAmazonmsgID.LogMessage(",\t" + n + ",\t" + messageAmazonRequestBatch.ElementAt(n).msg.QueueMessageId + ",\t" + amazonMessageID, true);
                            }
                            catch (Exception ex) { logManager_RunSummary.LogMessage(ex.Message, true); }                                
                    });
                    thrdSendEmail.Name = n.ToString();
                    lstThread.Add(thrdSendEmail);
                    thrdSendEmail.Start();
                    //logManager_MessageLogwithAmazonmsgID.LogMessage(",\t" + n, true);
                }
                foreach (Thread t in lstThread)
                {
                    t.Join();
                    //logManager_MessageLogwithAmazonmsgID.LogMessage(",\t" + t.Name, true);
                }
            }
            catch (Exception ex)
            {
                logManager_RunSummary.LogMessage(ex.Message, true);
            }

I have also tried parallel.foreach and asynch and await options... they also give the duplicates. I know that the lock will solve the problem but in my case the lock degrades the performance by a factor of 10.. that is my performance drops 10 times... coz putting the sendemail login in lock is blocking untill i get a return amazonmessageid from amazon...

Any help on this will be greatly appreciated. I am not a novice programmer but new to threading...


回答1:


Your lambda expression is capturing the loop variable n, so when your lambda executes, the value of n has already changed; you need to copy n to a local variable inside the loop. (assuming you're using C# 4 or earlier; C# 5 fixed that problem).

Another issue is that all your threads use the same amazonMessageID variable; you should declare it inside the lambda expression instead.

            foreach (int n in arrMessageid)
            {
                int n2 = n;
                thrdSendEmail = new Thread(() =>
                {
                        try
                        {
                            string amazonMessageID = SendSimpleEmail_Part2(messageAmazonRequestBatch.ElementAt(n2).req);
                            messageAmazonRequestBatch.ElementAt(n2).msg.AmazonMessageID = amazonMessageID;
                            logManager_MessageLogwithAmazonmsgID.LogMessage(",\t" + n2 , true);
                            //logManager_MessageLogwithAmazonmsgID.LogMessage(",\t" + n2 + ",\t" + messageAmazonRequestBatch.ElementAt(n2).msg.QueueMessageId + ",\t" + amazonMessageID, true);
                        }
                        catch (Exception ex) { logManager_RunSummary.LogMessage(ex.Message, true); }                                
                });
 ...



回答2:


I don't like that your threads share the same variables (I mean n and amazonMessageID), it is not thread safe and it may cause your problem. Moreover I suggest you to use Parallel.ForEach method, it can make your code easy. It could look like this:

try
{

     Parallel.ForEach(arrMessageid.Distinct(),
         n => 
         {
             try
             {
                 var amazonMessageID = SendSimpleEmail_Part2(messageAmazonRequestBatch.ElementAt(n).req);
                 messageAmazonRequestBatch.ElementAt(n).msg.AmazonMessageID = amazonMessageID;
                 logManager_MessageLogwithAmazonmsgID.LogMessage(",\t" + n , true);
             }
             catch (Exception ex)
             {
                 logManager_RunSummary.LogMessage(ex.Message, true); 
             }
         }
      );              

}
catch (Exception ex)
{
    logManager_RunSummary.LogMessage(ex.Message, true);
}


来源:https://stackoverflow.com/questions/21418263/creating-manual-threads-but-getting-duplicate-threads

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!