2013-03-06 26 views
4

在C#規範4.0節7.15.5.1:捕獲的變量如何同時暴露給多個執行線程?

注意,不像未捕獲的變量,捕獲的局部變量可以被 simulataneously暴露於多個執行線程。

「多線程執行」究竟意味着什麼?這是否意味着多個線程,多個執行路徑或其他?

E.G.

 private static void Main(string[] args) 
     { 
      Action[] result = new Action[3]; 
      int x; 
      for (int i = 0; i < 3; i++) 
      { 
       //int x = i * 2 + 1;//this behaves more intuitively. Outputs 1,3,5 
       x = i*2 + 1; 
       result[i] =() => { Console.WriteLine(x); }; 
      } 
      foreach (var a in result) 
      { 
       a(); //outputs 5 each time 
      } 

      //OR... 

      int y = 1;    
      Action one = new Action(() => 
      { 
       Console.WriteLine(y);//Outputs 1 
       y = 2;     
      }); 

      Action two = new Action(() => 
      { 
       Console.WriteLine(y);//Outputs 2. Working with same Y 
      }); 

      var t1 = Task.Factory.StartNew(one); 
      t1.Wait(); 
      Task.Factory.StartNew(two); 
      Console.Read(); 
     } 

這裏x展品基於其中x聲明不同的行爲。在y的情況下,多個線程捕獲並使用相同的變量,但IMO這種行爲很直觀。

它們指的是什麼?

回答

1

「多個執行線程」只是表示多個線程;即同時執行的多個線程。如果一個特定的變量暴露給多個線程,那麼這些線程中的任何一個都可以讀取並寫入該變量的值。

這是潛在的危險,應儘可能避免。如果您的方案允許,避免這種情況的一種可能性是在您的任務方法中創建變量的本地副本。

1

如果您修改代碼一點的第二部分:

 int y = 1; 
     Action one = new Action(() => 
     { 
      Console.WriteLine(y);//Outputs 1 
      y = 2; 
     }); 

     Action two = new Action(() => 
     { 
      Console.WriteLine(y);//Outputs 2. Working with same Y 
      y = 1; 
     }); 

     var t1 = Task.Factory.StartNew(one); 
     t1 = Task.Factory.StartNew(two); 
     t1.Wait(); 
     t1 = Task.Factory.StartNew(one); 
     t1.Wait(); 
     t1 = Task.Factory.StartNew(two); 

     Console.Read(); 

運行了幾次,或把它放在一個循環。它將輸出不同的,看似隨機的結果,例如, 1 1 1 21 2 1 2

多個線程正在訪問相同的變量和得到設置同時,這可能產生意外的結果。

1

請參閱下面的鏈接。

對外部變量n的引用被認爲是在委託創建時捕獲的。與局部變量不同,捕獲變量的生命週期一直延續到引用匿名方法的委託有資格進行垃圾回收。

換句話說,變量的內存位置是在方法創建並被共享到該方法時捕獲的。就像一個線程有權訪問該變量減去匿名方法一樣。有一個編譯器警告,在某些情況下會發生,它會建議您移動到本地temp變量,以避免造成意想不到的後果。

MSDN Anonymous Methods