C# singleton中的新线程从未完成
我有一个简单的单身班:C# singleton中的新线程从未完成,c#,multithreading,C#,Multithreading,我有一个简单的单身班: namespace TestApp { public class MySingleton { static MySingleton() { } private static readonly MySingleton instance = new MySingleton(); private bool threadFinished = false; publi
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;
}
}
}
当我试图通过以下方式来稳定此过程:
var ir = MySingleton.Instance.IsReady;
它永远不会结束——while循环是无限的。为什么?以及如何在构造函数的singleton中运行反向线程?您处于死锁状态。在执行静态构造函数之前,不允许从其他线程调用任何方法。静态构造函数也包括静态字段初始化器 由于使用while循环阻塞调用线程,静态字段初始化将不会完成,新线程也不允许执行
MyAction
您的代码与Eric演示死锁的代码几乎相同
引用eric对同一答案的评论,为什么会死锁:
@Lieven:静态构造函数必须运行不超过一次,并且
必须在第一次调用类中的任何静态方法之前运行。主要
是一个静态方法,因此主线程调用静态构造函数。到
确保它只运行一次,CLR将取出一个不可用的锁
释放,直到静态操作完成。当ctor启动一个新的
线程,该线程还调用静态方法,因此CLR尝试
获取锁以查看是否需要运行ctor。主线
同时“加入”被阻塞的线程,现在我们有了死锁
Eric Lippert 2012年1月17日14:28
回答你的问题;不要那样做。通过启动线程并等待它,您将一无所获。只需同步运行该方法。您处于死锁状态。在执行静态构造函数之前,不允许从其他线程调用任何方法。静态构造函数也包括静态字段初始化器 由于使用while循环阻塞调用线程,静态字段初始化将不会完成,新线程也不允许执行
MyAction
您的代码与Eric演示死锁的代码几乎相同
引用eric对同一答案的评论,为什么会死锁:
@Lieven:静态构造函数必须运行不超过一次,并且
必须在第一次调用类中的任何静态方法之前运行。主要
是一个静态方法,因此主线程调用静态构造函数。到
确保它只运行一次,CLR将取出一个不可用的锁
释放,直到静态操作完成。当ctor启动一个新的
线程,该线程还调用静态方法,因此CLR尝试
获取锁以查看是否需要运行ctor。主线
同时“加入”被阻塞的线程,现在我们有了死锁
Eric Lippert 2012年1月17日14:28
回答你的问题;不要那样做。通过启动线程并等待它,您将一无所获。只需同步运行该方法。在创建singleton实例以使其线程安全时,请查看
在这里可以找到如何在singleton模式中使用它的示例:当您创建singleton实例以使其线程安全时,请查看
在这里可以找到如何在单例模式中使用它的示例:这很有效。我不是单身专家——如果这违反了任何规则,请有人指出。但这可以打破僵局。我将您的代码复制到一个控制台应用程序中,如果您在其他地方使用它,请进行适当调整
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;
}
}
这很有效。我不是单身专家——如果这违反了任何规则,请有人指出。但这可以打破僵局。我将您的代码复制到一个控制台应用程序中,如果您在其他地方使用它,请进行适当调整
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;
}
}
可以将threadFinished声明为volatile,但请使用谷歌搜索更好的单例模式。可以将threadFinished声明为volatile,但请使用谷歌搜索更好的单例模式。谢谢您的回答。但我需要启动新的线程,然后在它的SynchornizationContext上运行代码。那么,对于只启动一次新的反向线程,什么是最好的解决方案呢?为什么它必须在另一个线程中?我看不出确切的问题。你能解释一下吗?这个新线程从执行WebCore.Run(),这样线程就按照文档中的指定被阻塞了。WebCore,Run()正在阻塞线程,该线程在其上执行,因此我需要创建新线程并只运行WebCore.Run()一次。在我获得SynchronizationContext.Current后,它将在并行循环中使用,您可以在另一个线程中启动它。但不要等待。i、 e只要在(!threadFinished)时删除
,就可以了。我遗漏了什么吗?这不是因为myContext(从SynchronizationContext.Current设置它的新线程)在WebCore初始化之前是空的-需要1-2 sek。所以我需要等待WebCore初始化。MyAction()包含WebCore.Started+=(s,e)=>{myContext=SynchronizationContext.Current;}代码>在删除之后,而myContext.Send()会抛出例外提示以获取您的答案。但我需要启动新的线程,然后在它的SynchornizationContext上运行代码。那么,对于只启动一次新的反向线程,什么是最好的解决方案呢?为什么它必须在另一个线程中?我看不出确切的问题。你能解释一下吗?这个新线程从执行WebCore.Run(),这样线程就按照文档中的指定被阻塞了。WebCore,Run()正在阻塞线程,该线程在其上执行,因此我需要创建新线程并只运行WebCore.Run()一次。在我获得SynchronizationContext.Current后,它将在并行循环中使用,您可以在另一个线程中启动它。但不要等待。i、 e只要在(!threadFinished)
时删除,就可以了。我遗漏了什么吗?这不是因为myContext(从SynchronizationContext.Current设置它的新线程)在WebCore初始化之前是空的-需要1-2 sek。所以我需要等待WebCore初始化。MyAction()包含WebCore.Started+=(s,e)=>{myContext=SynchronizationContext.Current;}代码>之后