2013-04-02 43 views
2

我試圖添加線程到一個靜態類,我遇到了一堆問題。我讀this thread和它鏈接到的博客文章,我想我明白髮生了什麼。但我不明白,爲什麼並行For循環仍然有效,如本例:並行For不會導致靜態構造函數中的死鎖?

using System; 
using System.Threading; 
using System.Threading.Tasks; 

namespace ThreadingTest 
{ 
    public static class TestClass 
    { 
     public static int AwesomeNum = 43; 

     static TestClass() 
     { 
      string[] x = { "deal", "witch", "panda"}; 

      //does not cause a deadlock? huh? 
      Parallel.For(0, x.Length, i => 
       { 
        Console.WriteLine(x[i]); 
       }); 

      //results in a deadlock 
      //Parallel.Invoke(writesomething, writesomethingelse); 

      //results in deadlock 
      Thread thread = new Thread(new ThreadStart(() => 
      { 
       Console.WriteLine("there is a bear in my soup"); 
      })); 

      thread.Start(); 
      thread.Join(); 
     } 

     private static void writesomething() 
     { 
      Console.WriteLine("writing something"); 
     } 

     private static void writesomethingelse() 
     { 
      Console.WriteLine("writing something else."); 
     } 
    } 
} 


using System; 

namespace ThreadingTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine(TestClass.AwesomeNum.ToString()); 
     } 
    } 
} 
+1

您可能會對我最近關於靜態構造函數語義的一系列文章感興趣。 http://ericlippert.com/2013/02/06/static-constructors-part-one/ –

回答

7

以下確實導致死鎖:

Parallel.For(0, x.Length, i => { 
    Console.WriteLine(i); 
}); 

有什麼區別?

我上面寫的lambda表達式被編譯爲TestClass裏面的一個方法。你在你的例子中寫的那個也是如此。

您在並行表達式i => Console.WriteLine(x[i])中編寫的lambda被編譯到另一個編譯器生成的類中,因爲它捕獲了x。所以執行它需要靜態初始化閉包類,但不是TestClass

所以與Parallel vs任何其他線程機制無關。這只是需要生成閉包對象的lambda和不包含閉包對象的lambda之間的區別。

請注意,我正在描述當前編譯器的行爲。這種行爲可以在相關的規範中找到,或者可以是實現定義的。我沒看過。

+2

C#規範中詳細介紹了閉包類如何實現的細節。 –