private static Thread thread;
private static List<object> items = new List<object>();
static Program()
{
thread = new Thread(() =>
{
foreach (var item in items)
{
item.Name = "ABC";
}
Thread.Sleep(3600);
});
thread.Start();
}
private static void Main(string[] args)
{
var item = items.Where(i => i.Name == "ABC").FirstOrDefault();
if(item != null)
{
items.Remove(item);
}
}
如您所见,在使用List开始的应用程序上启动了线程,在列表上执行了一些操作,并且主线程使用了相同的List。
当新线程的foreach循环中的代码正在执行时,同时foreach循环也被执行,它会抛出错误,你无法修改列表。
知道如何克服这个问题吗?
由于
答案 0 :(得分:0)
您正在谈论的主题是线程安全性
要完成此任务,您必须使用同步方法
修改强>
对不起那个,当然是C#,请看这里: http://msdn.microsoft.com/en-us/library/ms173179.aspx
它与java中的同步几乎相同,你只需要在使用它的过程中锁定对象,这样你的线程就会保持安全
请注意,当对象被锁定时,尝试访问该对象的所有其他线程都必须等待,这可能会导致死锁
答案 1 :(得分:0)
在您的示例中,您不修改枚举中的集合。但是,您要在枚举之外修改集合,如果在枚举期间发生这种情况,您将获得异常InvalidOperationException: Collection was modified
。
来自MSDN:
List(T)可以同时支持多个读者,只要 集合未被修改。列举一个集合是 本质上不是一个线程安全的程序。在罕见的情况下 枚举与一个或多个写访问争用,唯一的方法 确保线程安全是在整个过程中锁定集合 枚举即可。允许多个访问集合 阅读和写作的线程,你必须实现自己的 同步。
private static Thread thread;
private static List<object> items = new List<object>();
private Object theLock = new Object();
static Program()
{
thread = new Thread(() =>
{
lock(theLock)
{
foreach (var item in items)
{
item.Name = "ABC";
}
}
Thread.Sleep(3600);
});
thread.Start();
}
private static void Main(string[] args)
{
lock(theLock)
{
var item = items.Where(i => i.Name == "ABC").FirstOrDefault();
if(item != null)
{
items.Remove(item);
}
}
}
答案 2 :(得分:-1)
您确定这是一个多线程问题吗?列表是相对线程安全的,添加和删除方法都足够快(据我所知)MS不会将它识别为问题,不像Queue和ConcurrentQueue
请注意,使用foreach循环访问时无法修改Collection
List<int> integers = new List<int>(new int[] { 1,2,3,4,5,} );
foreach(int i in integers)
integers.Add(1); // Will throw an InvalidOperationException