多线程和锁定

时间:2012-05-17 04:24:41

标签: c# multithreading collections

我在多线程主题中有一个问题,如描述

    private List<Email> emails = new List<Email>();

    private void AddEmail(Email email)
    {
        lock (this.emails)
        {
            this.emails.Add(email);
        }
    }

    private void ReadEmails()
    {
        foreach (Email email in this.emails)
        {
            Print(email);
        }
    }

假设ReadEmails方法持续10秒,并且此时调用AddEmail。那么是否会发生错误?

2 个答案:

答案 0 :(得分:2)

您的ReadEmails方法不是线程安全的。你有几个选择。

选项#1:

您可以在整个lock循环中放置foreach

private void ReadEmails()
{
  lock (emails)
  {
    foreach (Email email in this.emails)
    {
      Print(email);
    }
  }
}

选项#2:

您可以在lock内制作列表的副本。然后你可以无锁地重复复制。

private void ReadEmails()
{
  List<Email> copy;
  lock (emails)
  {
    copy = new List<Email>(this.emails);
  }
  foreach (Email email in copy)
  {
    Print(email);
  }
}

答案 1 :(得分:1)

你一定要在Read方法中添加Lock方法。如果您不这样做,则有可能在尚未完成读取过程时添加电子邮件。由于foreach方法要求在迭代期间其集合不可更改,因此将引发异常。

 private void ReadEmails()
    {
        lock(emails) {
             foreach (Email email in this.emails) {
                Print(email);
             }
        }
    }