我有2个Threads
。其中一个反复修改 List
。其他尝试访问 List
,但通常会抛出System.InvalidOperationException
。
我尝试lock
对象List
,但没有帮助。
public static void Main()
{
List<int> list = new List<int>();
// A thread that repeatedly modifies the list
Thread listAddThread = new Thread(() =>
{
while(true)
{
list.Add(0);
Thread.Sleep(1);
}
});
listAddThread.Start();
// Wait to fill up the list
Thread.Sleep(50);
// Lock the list from other threads till the operation completes
lock(list)
{
foreach(var entry in list)
{
DoSomeStuffThatTakesALotOfTime(entry);
}
}
}
public static void DoSomeStuffThatTakesALotOfTime(int i)
{
Thread.Sleep(10);
Console.WriteLine(i);
}
我希望lock(list)
将阻止其他线程访问list
。
答案 0 :(得分:2)
如果两个不同的代码块使用lock(list)
,则每个代码块都必须获得锁。一个将不会获取锁并执行,直到另一个已完成并释放锁。 (当然,这就是我们使用它的原因-以便两个代码块不会同时执行。)
但是在这种情况下,您只需要在方法的第二部分中使用一次lock
。由于没有其他试图获取该锁的“竞争”代码,因此它根本不执行任何操作。
也不能保证listAddThread
将在方法的第二部分开始迭代列表之前完成。这意味着您可能会开始尝试迭代列表,而您启动的其他线程正在向列表中添加该列表。根据例外情况,这可能不是-这就是 发生的情况。
while(true)
循环将永远不会停止执行(true始终为true),因此无论等待时间是50ms还是5000ms,您都不会停止添加到列表中。但是,即使该循环确实终止了,也无法保证50ms等待将是足够的时间或太多的时间。最好只编写我们的代码,以便需要按顺序执行的所有内容总是始终按顺序执行,而不是试图猜测需要多长时间。