2016-01-29 30 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

相关问题