2016-01-29 91 views
0

我有簡單的單例類:在單新線程永遠不會結束

namespace TestApp 
{ 
    public class MySingleton 
    { 
     static MySingleton() 
     { 
     } 

     private static readonly MySingleton instance = new MySingleton(); 
     private bool threadFinished = false; 
     public bool IsReady = false; 

     private MySingleton() 
     { 
      Thread t = new Thread(MyAction); 
      t.Start(); 

      while (!threadFinished) 
       Thread.Sleep(10); 
     } 

     public static MySingleton Instance 
     { 
      get { return instance; } 
     } 

     private void MyAction() 
     { 
      threadFinished = true; 
     } 
    } 
} 

當我試圖instatiate這種情形:

var ir = MySingleton.Instance.IsReady; 

它永遠不會結束 - while循環是無限的。爲什麼?以及如何在構造函數中在單例中運行backround線程?

+0

它可以將threadFinished聲明爲volatile,但請google改爲更好的單例模式。 – fhogberg

回答

1

這工作。我不是辛格爾頓的專家 - 如果這違反了任何規則,有人請指出。但是這個問題解決了僵局。我將您的代碼複製到控制檯應用程序中,如果您在其他地方使用它,請適當調整。

namespace TestApp 
{ 
class Program 
{ 
    static void Main(string[] args) 
    { 
     while (!MySingleton.Instance.IsReady) 
      Thread.Sleep(100); 
     Console.WriteLine("Done"); 
     Console.Read(); 
    } 
} 

public class MySingleton 
{ 
    static MySingleton() 
    { 
    } 

    private static readonly MySingleton instance = new MySingleton(); 
    private static bool threadFinished = false; 
    public bool IsReady 
    { 
     get { return threadFinished; }  
    } 

    private MySingleton() 
    { 
     Thread t = new Thread(new ThreadStart(MyAction)); 

     t.Start(); 
    } 

    public static MySingleton Instance 
    { 
     get { return instance; } 
    } 
    static void MyAction() 
    { 
     threadFinished = true; 
    } 
} 
2

你是僵局。在執行靜態構造函數之前,不允許從另一個線程調用任何方法。靜態構造函數也包括靜態字段initalizers。

既然你阻擋while循環調用線程,靜態字段初始化將不完整,並且新的線程將既不能被允許執行MyAction無論是。

您的代碼幾乎是相同的this code埃裏克演示了僵局。

並引述相同的答案Eric的評論爲什麼它死鎖:

@Lieven:靜態構造函數必須不止一次運行沒有更多的,它 必須在第一次調用任何靜態方法之前運行類。主 是一個靜態方法,所以主線程調用靜態ctor。至 確保它只運行一次,CLR取出一個不是 的鎖,直到靜態ctor完成。當構造函數啓動一個新線程 ,該線程還調用一個靜態方法,所以CLR試圖 採取鎖,看它是否需要運行構造函數。主線程 與此同時「加入」被阻塞的線程,現在我們有了我們的死鎖。 - Eric Lippert 12年1月17日在14:28

要回答你的問題;不要這樣做。你通過開始一個線程並等待它而獲得任何東西。只需簡單地同步運行該方法。

+0

感謝您的回答。但是我需要開始新的線程 - 並且在SynchornizationContext上運行代碼。那麼只有一次啓動新的後臺線程的最佳解決方案是什麼? – john93230

+0

爲什麼它必須在另一個線程?我沒有看到確切的問題。你能解釋一下嗎? –

+0

新線程從http://docs.awesomium.net/html/M_Awesomium_Core_WebCore_Run.htm執行WebCore.Run()以便該線程按照doc中的指定被阻止。 WebCore,Run()阻塞了線程,因此我需要創建新的並且只運行WebCore.Run()一次。在獲得SynchronizationContext.Current後,它將用於並行循環 – john93230

相關問題