AutoresetEvent和Singleton问题

时间:2012-05-24 17:23:56

标签: c# singleton autoresetevent

有人可以告诉我以下代码有什么问题吗?理想情况下,它应首先启动一个线程,然后等待set事件。而不是它不会启动线程而只是卡在WaitOne()上。

我很想知道线程发生了什么,为什么?

class Program
{   
    static void Main(string[] args)
    {
        Testing t = Testing.Instance;
        Console.Read();
    }
}


class Testing
{
    private static AutoResetEvent evt = new AutoResetEvent(false);
    public static Testing Instance = new Testing();

    private Testing()
    {
        Create();
        evt.WaitOne();
        Console.WriteLine("out");
    }

    private void Create()
    {
        Console.WriteLine("Starting thread");
        new Thread(Print).Start();
    }

    private void Print()
    {
        Console.WriteLine("started");
        evt.Set();
    }
}

修改 到目前为止,@ BrinkGlass提供的描述是有道理的。但是将代码更改为以下代码允许另一个线程可以在不完成构造函数的情况下访问实例方法。(建议@NicoSchertler)。

private static Testing _Instance;

public static Testing Instance
{
get
{
    if (_Instance == null)
        _Instance = new Testing();
    return _Instance;
}
}

3 个答案:

答案 0 :(得分:5)

我怀疑这种行为的根本原因是,在构造函数完成执行之前,生成的线程无法访问Print方法 - 但构造函数永远不会完成执行,因为它正在等待仅触发的信号Print方法。

使用长evt.WaitOne()调用替换Thread.Sleep()确认相同的行为 - 构造函数必须在对象的任何实例方法可以从另一个线程执行之前完成运行。

答案 1 :(得分:3)

问题是第二个线程创建得太早。我不知道为什么,但是在主程序启动之前启动时,它将无法执行。

您应该在其原始版本中使用单例模式。这将有效。

private static Testing _Instance;

public static Testing Instance
{
    get
    {
        if (_Instance == null)
            _Instance = new Testing();
        return _Instance;
    }
}

此外,您不应该将evt变量设为静态。在大多数情况下,实例变量应该是单例类的唯一静态成员。

答案 2 :(得分:0)

我的猜测是静态字段初始化的相对时间问题。请尝试在evt的构造函数中初始化Testing

private static AutoResetEvent evt;
public static Testing Instance = new Testing();

private Testing()
{
    evt = new AutoResetEvent(false);
    Create();
    evt.WaitOne();
    Console.WriteLine("out");
}

我应该注意到这只是一个猜测 - 我认为这段代码可以正常工作。