我在多线程主题中有一个问题,如描述
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。那么是否会发生错误?
答案 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);
}
}
}