-1
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 循环也被执行时,它会抛出您无法修改列表的错误。

知道如何克服这个问题吗?

谢谢

4

3 回答 3

0

您正在谈论的主题是线程安全

为此,您必须使用同步方法

编辑:

抱歉,当然是 C#,请看这里:http: //msdn.microsoft.com/en-us/library/ms173179.aspx

它与 java 中的同步几乎相同,您只需在使用它的持续时间内锁定对象,这样您的线程就可以保持安全

请注意,当对象被锁定时,所有其他试图访问该对象的线程都必须等待,这可能会导致死锁

于 2013-03-12T13:09:52.900 回答
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);
    }
  }
} 
于 2013-03-12T13:38:43.780 回答
-1

你确定这是一个多线程问题吗?List 是相对线程安全的,Add 和 remove 方法都足够快(据我所知)MS 不认为这是一个问题,这与 Queue 和 ConcurrentQueue 不同

请注意,您不能在使用 foreach 循环遍历集合时修改集合,因此

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
于 2013-03-12T13:07:30.277 回答