创建手动线程 - 但获取重复的线程

时间:2014-01-28 22:27:57

标签: c# multithreading duplicates

问题:获取重复的项目,即创建的线程数多于数组大小... 嗨伙计们,我在循环中为数组的每个元素创建线程。真正的用途是使用亚马逊ses发送一批消息。消息存储在messageamazonRequestBatch中,循环遍历批处理并发送消息。

这是代码:

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

我也尝试过parallel.foreach和asynch并等待选项......他们也提供了重复项。我知道锁将解决问题,但在我的情况下,锁将性能降低了10倍......这是我的性能下降了10倍...因为将sendemail登录锁定阻止直到我得到一个返回amazonmessageid来自亚马逊...

对此的任何帮助将不胜感激。我不是新手程序员,而是线程新手......

2 个答案:

答案 0 :(得分:2)

你的lambda表达式正在捕获循环变量n,因此当你的lambda执行时,n的值已经改变了;您需要将n复制到循环内的局部变量。 (假设您使用的是C#4或更早版本; C#5解决了这个问题)。

另一个问题是所有线程都使用相同的amazonMessageID变量;你应该在lambda表达式中声明它。

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

答案 1 :(得分:0)

我不喜欢您的线程共享相同的变量(我的意思是namazonMessageID),它不是线程安全的,它可能会导致您的问题。此外,我建议您使用Parallel.ForEach方法,它可以使您的代码更容易。它看起来像这样:

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