问题:获取重复的项目,即创建的线程数多于数组大小... 嗨伙计们,我在循环中为数组的每个元素创建线程。真正的用途是使用亚马逊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来自亚马逊...
对此的任何帮助将不胜感激。我不是新手程序员,而是线程新手......
答案 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)
我不喜欢您的线程共享相同的变量(我的意思是n
和amazonMessageID
),它不是线程安全的,它可能会导致您的问题。此外,我建议您使用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);
}