在两个线程之间共享列表<t> </t>

时间:2013-03-12 13:01:10

标签: c# multithreading

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

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

由于

3 个答案:

答案 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