【问题标题】:parallel.foreach loop issue: An item with the same key has already been addedparallel.foreach 循环问题:已添加具有相同键的项目
【发布时间】:2017-01-07 21:46:32
【问题描述】:

想看看你们中的某个人能否对此有所了解。 在下面的代码中已经添加了获取具有相同密钥的项目的异常:

foreach (EmailMessage m in findResultsSentItems)
{
    em.Add(m);
}
lstMailContactDeatils.Clear();
Parallel.ForEach(em,
        myItem =>
        {
            myItem.Load();
            foreach (EmailAddress e in myItem.ToRecipients)
            {
                try
                {
                    MailContactDeatils _MailContactDeatils1 = new MailContactDeatils();
                    _MailContactDeatils1.MailID = e.Address;
                    _MailContactDeatils1.DisplayName = e.Name;
                    _MailContactDeatils1.SentTime = myItem.DateTimeSent.ToString();
                //    if(lstMailContactDeatils.Contains())
                    lstMailContactDeatils.Add(_MailContactDeatils1);
                }
                catch (Exception e1) { exceptions.Enqueue(e1); }
            }
            foreach (EmailAddress e in myItem.CcRecipients)
            {
                try
                {
                    MailContactDeatils _MailContactDeatils2 = new MailContactDeatils();
                    _MailContactDeatils2.MailID = e.Address;
                    _MailContactDeatils2.DisplayName = e.Name;
                    _MailContactDeatils2.SentTime = myItem.DateTimeSent.ToString();
                    lstMailContactDeatils.Add(_MailContactDeatils2);
                }
                catch (Exception e2) { exceptions.Enqueue(e2); }
            }
        });

LINQ 语句是我抛出 ArgumentExcpetion 的地方:已添加具有相同键的项目

【问题讨论】:

  • 您是否在 MailContactDetails 中定义了自定义相等比较?
  • 什么是lstMailContactDeatils
  • lstMailContactDeatils 是 MailContactDeatils 类型的列表..... public class MailContactDeatils { public string DisplayName { get;放; } 公共字符串 MailID { 获取;放; } 公共字符串 SentTime { 获取;放; } }
  • 您的代码未显示此处必不可少的部分。你如何与上下文交互?无论如何,您永远不应该从多个线程中处理一个上下文实例。这意味着:将Parallel.ForEach 替换为普通的foreach
  • 如果读取 500 条记录需要 那么 长,那么您的问题出在其他地方。不要试图通过并行化来修复糟糕的查询。

标签: c# linq list foreach parallel.foreach


【解决方案1】:

当您使用Parallel 时,您需要先锁定才能添加。

object padlock = new object();

foreach (EmailMessage m in findResultsSentItems)
{
    em.Add(m);
}
lstMailContactDeatils.Clear();
Parallel.ForEach(em,
        myItem =>
        {
            myItem.Load();
            foreach (EmailAddress e in myItem.ToRecipients)
            {
                try
                {
                    MailContactDeatils _MailContactDeatils1 = new MailContactDeatils();
                    _MailContactDeatils1.MailID = e.Address;
                    _MailContactDeatils1.DisplayName = e.Name;
                    _MailContactDeatils1.SentTime = myItem.DateTimeSent.ToString();

                    lock(padlock) {
                        if(!lstMailContactDeatils.Contains(_MailContactDeatils1))
                            lstMailContactDeatils.Add(_MailContactDeatils1);
                    }
                }
                catch (Exception e1) { exceptions.Enqueue(e1); }
            }
            foreach (EmailAddress e in myItem.CcRecipients)
            {
                try
                {
                    MailContactDeatils _MailContactDeatils2 = new MailContactDeatils();
                    _MailContactDeatils2.MailID = e.Address;
                    _MailContactDeatils2.DisplayName = e.Name;
                    _MailContactDeatils2.SentTime = myItem.DateTimeSent.ToString();
                    lock(padlock) {
                        if (!lstMailContactDeatils.Contains(_MailContactDeatils2))
                            lstMailContactDeatils.Add(_MailContactDeatils2);
                    }
                }
                catch (Exception e2) { exceptions.Enqueue(e2); }
            }
        });

【讨论】:

  • 仍然出现异常:已添加具有相同密钥的项目...异常随机发生,例如运行代码时 6 次中有 2 次​​span>
  • 是在第一个 foreach 循环还是第二个循环上抛出?
  • 这个锁实际上违背了并行处理的目的。但是 OP 无论如何都不应该使用并行循环(见上文)。
  • 我不知道发生在哪个循环错误,无法调试 Parallel.ForEach,因为它整个代码都被视为单个语句......我正在使用并行处理来提高性能。
  • @GertArnold,我不同意。只有一小部分 forloop 被锁定。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-15
  • 2013-04-04
  • 2013-02-16
  • 2022-09-29
  • 1970-01-01
相关资源
最近更新 更多