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

C# 创建手动线程-但获取重复线程,c#,multithreading,duplicates,C#,Multithreading,Duplicates,问题:获取重复项,即创建的线程数超过数组大小。。。 大家好,我正在为数组的每个元素创建循环中的线程。真正的用途是使用AmazonSES发送一批消息。消息存储在messageamazonRequestBatch中,循环在该批中运行并发送消息 代码如下: Thread thrdSendEmail; try { string amazonMessageID = string.Empty; L

问题:获取重复项,即创建的线程数超过数组大小。。。 大家好,我正在为数组的每个元素创建循环中的线程。真正的用途是使用AmazonSES发送一批消息。消息存储在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);
            }
线程thrdsendmail;
尝试
{
string amazonMessageID=string.Empty;
List lsthread=new List();
foreach(arrMessageid中的int n)
{
thrdsendmail=新线程(()=>
{
尝试
{
amazonMessageID=SendSimpleMail_Part2(messageAmazonRequestBatch.ElementAt(n.req));
messageAmazonRequestBatch.ElementAt(n.msg.AmazonMessageID=AmazonMessageID;
logManager\u messagelogwithamazonsgid.LogMessage(“,\t”+n,true);
//logManager\u messagelogwithamazonsgid.LogMessage(,\t“+n+”,\t“+messageAmazonRequestBatch.ElementAt(n).msg.QueueMessageId+,\t“+amazonsmessageid,true);
}
catch(异常ex){logManager_RunSummary.LogMessage(ex.Message,true);}
});
thrdsendmail.Name=n.ToString();
添加(thrdsendmail);
thrdsendmail.Start();
//logManager\u messagelogwithamazonsgid.LogMessage(“,\t”+n,true);
}
foreach(LSTHREAD中的螺纹t)
{
t、 Join();
//logManager_messagelogwithamazonsgid.LogMessage(“,\t”+t.Name,true);
}
}
捕获(例外情况除外)
{
logManager\u RunSummary.LogMessage(例如Message,true);
}
我还尝试了parallel.foreach和asynch以及wait选项。。。他们还提供了副本。我知道锁可以解决问题,但在我的情况下,锁会将性能降低10倍。。那就是我的表现下降了10倍。。。因为将sendemail登录锁定是阻塞的,直到我从amazon获得返回的amazonmessageid


在此方面的任何帮助都将不胜感激。我不是一个新手程序员,但对线程还是新手…

我不喜欢你的线程共享相同的变量(我的意思是
n
amazonMessageID
),它不是线程安全的,可能会导致你的问题。此外,我建议您使用该方法,它可以使您的代码变得简单。它可能是这样的:

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

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

您使用的是C#5还是更早的版本?C#4.0-->Microsoft Visual C#2010 01018-532-2002102-70050Hi Thomas,谢谢您的建议。我尝试了你的建议,但仍然给了我副本嗨,托马斯,我为这个做的概念验证也给了我副本。ThreadLocal ThreadName=new ThreadLocal(()=>{return“Thread”+Thread.CurrentThread.ManagedThreadId;});Action Action=()=>{bool repeat=ThreadName.IsValueCreated;logManager_MessageLogwithAmazonmsgID.LogMessage(“,\t”,true);};并行调用(动作)@user3241488,好吧,你说的“重复”到底是什么意思?它是否多次发送相同的消息?您确定arrMessageid只包含不同的值吗?你想用ThreadLocal做什么?你在评论中发布的代码毫无意义,也没有任何用处……是的,它会多次发送一些消息,例如,如果我发送50000条消息,我会收到500-1000条重复消息。所以我发布的代码只是一个概念证明。。这个threadlocal必须发送一条单独的消息,然后等待amazon的响应,我将在我的数据库中更新该响应。你也可以在这里查看我的完整代码:嗨,Tony,我也尝试过实现你的建议,但它仍然给了我重复的建议。但是,我没有使用distinct,因为它给了我错误31。无法从用法推断方法“System.Threading.Tasks.Parallel.ForEach(System.Collections.Generic.IEnumerable,System.Action)”的类型参数。尝试显式指定类型参数。嗨,Tony,我知道如何使用distinct**(Parallel.ForEach(messageAmazonRequestBatch.distinct(),)但这也给了我重复…因此,如果我运行4000个批次,我会得到200-500个副本。@user3241488 Hm,
arrMessageid
?在代码中使用
foreach(arrMessageid中的int n)
,它不应该是某种
IEnumerable
?arrMessageid是一个简单的整数数组,它保存着消息的索引位置。但是我也用list和ConcurrentBag对象尝试过这段代码。啊,好吧,但为什么我要尝试传递到Parallel.ForEach
messageAmazonRequestBatch
而不是
arrMessageid.Distinct()