1

私はこのコードを持っています:

    private void timer1_Tick(object sender, EventArgs e)
    {
        MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
    }

タイマーは有効で、間隔は100です。

これにより、現在のメッセージボックスが閉じられるまで次のイベントを単にブロックすることを期待していたときに、無限の数のメッセージボックスが互いに重なり合って表示されます。

より複雑なアプリケーションでは、これは編集不可能な結果につながる可能性があり、複数のスレッドが同じ関数にアクセスできるかのようになりますが、実際には同じスレッドです。

なぜこうなった ?

4

2 に答える 2

2

メッセージボックスは、メッセージキューをポンプするモーダルダイアログです。そして、GUIスレッドのメッセージキューに投稿されるため、タイマーティックメッセージを起動できます。

これは、GUIスレッドに表示されるモーダルダイアログの場合は常に当てはまります。各スレッドにはメッセージキューが1つしかないため、モーダルダイアログのメッセージポンプはタイマーティックメッセージをプルします。

于 2013-02-01T19:44:43.580 に答える
1

それは、まさにあるべき姿で起こっています。tick イベントはメッセージ ループによって強化され (スレッド化されたバリアントを使用している場合を除く)、何らかの方法でメッセージ ループをブロックしない限り (Thread.Sleepメッセージ ベースのコード実行を考えるか、または非メッセージ ベースで)、繰り返し呼び出されます。

メッセージ ボックスはブロックされません。これは単なる別のウィンドウであり、アプリケーションのメッセージ ポンプが機能している限りウィンドウも機能するため、ティックが発生するたびに新しいダイアログを作成して積み重ねることができます。

これに対する簡単な解決策は、次のようなものです。

private void timer1_Tick(object sender, EventArgs e)
{
    timer1.Stop();
    MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
    timer1.Start();
}

これにより、タイマーが停止し、ダイアログが表示され、ダイアログが閉じられた後にタイマーが回復できるようになります。これは、ダイアログの永続的なスタックではなく、1 つのダイアログのみを取得することを意味します。

于 2013-02-01T19:45:36.040 に答える