-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);
      }

} 

ご覧のとおり、リストを使用して開始されたアプリケーションでスレッドが開始され、リストに対して何らかの操作が実行され、同じリストがメインスレッドによって使用されます。

新しいスレッドの 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)は、コレクションが変更されない限り、複数のリーダーを同時にサポートできます。コレクションの列挙は、本質的にスレッドセーフな手順ではありません。列挙が 1 つ以上の書き込みアクセスと競合するまれなケースでは、スレッドの安全性を確保する唯一の方法は、列挙全体でコレクションをロックすることです。読み取りおよび書き込みのために複数のスレッドがコレクションにアクセスできるようにするには、独自の同期を実装する必要があります。

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 メソッドの両方が (私の知る限り) 十分に高速であるため、Queue や ConcurrentQueue とは異なり、MS はそれを問題として認識しません。

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 に答える