3

次のコードの何が問題になっているのか教えてもらえますか?理想的には、最初にスレッドを開始してから、設定されたイベントを待つ必要があります。その代わりに、スレッドを開始せず、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();
    }
}

編集: これまでのところ、@BrokenGlassによって提供された説明は理にかなっています。ただし、コードを次のコードに変更すると、別のスレッドがコンストラクターを完了せずにインスタンスメソッドにアクセスできるようになります(@NicoSchertlerによる提案)。

private static Testing _Instance;

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

3 に答える 3

5

この動作の根本的な原因は、生成されたスレッドがPrintコンストラクターの実行が完了するまでメソッドにアクセスできないことだと思いますが、メソッドからのみトリガーされるシグナルを待機しているため、コンストラクターは実行を終了しませんPrint

evt.WaitOne() を長い呼び出しに置き換えるとThread.Sleep()、同じ動作が確認されます。オブジェクトのインスタンス メソッドが別のスレッドから実行される前に、コンストラクターの実行が終了する必要があります。

于 2012-05-24T17:28:14.237 に答える
3

問題は、2 番目のスレッドの作成が早すぎることです。理由はわかりませんが、メインプログラムが起動する前に起動すると実行されません。

元のバージョンでシングルトン パターンを使用する必要があります。これは機能します。

private static Testing _Instance;

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

さらに、evt 変数を静的にしないでください。ほとんどの場合、インスタンス変数はシングルトン クラスの唯一の静的メンバーにする必要があります。

于 2012-05-24T17:41:15.587 に答える
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");
}

これは単なる推測に過ぎないことに注意してください。このコードは正常に機能すると思います。

于 2012-05-24T17:30:17.420 に答える