0

この質問に基づいて、Jim Mischel の推奨に基づいてソリューションに waithandles/eventwaithandle を使用することにしました。私は「ほぼ」それを機能させています。ここにコードがあります

Private Sub InitDeploymentCheck()
moDeploymentCheck = New TRS.Deployment.TRSDeploymentCheck(EnvironmentVariables.Environment, AppDomain.CurrentDomain.BaseDirectory.Contains("bin"), MDIMain)
AddHandler moDeploymentCheck.DeploymentNeeded,
    Sub()
        moTimer = New System.Windows.Forms.Timer()
        moTimer.Interval = 300000 '5 minutes
        moTimer.Enabled = True
        AddHandler moTimer.Tick,
            Sub()
                'check to see if the message box exist or not before throwing up a new one

                'check to see if the wait handle is non signaled, which means you shouldn't display the message box
                If waitHandle.WaitOne(0) Then
                    'set handle to nonsignaled
                    waitHandle.Reset()
                    MessageBox.Show(MDIMain, "There is a recent critical deployment, please re-deploy STAR to get latest changes.", "Critical Deployment", MessageBoxButtons.OK, MessageBoxIcon.Warning)
                    'set the handle to signaled
                    waitHandle.Set()
                End If


            End Sub
        waitHandle.Set()
        MessageBox.Show(MDIMain, "There is a recent critical deployment, please re-deploy STAR to get latest changes.", "Critical Deployment", MessageBoxButtons.OK, MessageBoxIcon.Warning)
    End Sub
End Sub

繰り返しますが、これはほとんどすべてのアプリケーションが継承する基本フォームからのものです。単一のアプリを使用している場合、完全に機能します。ベース フォームから継承する複数のアプリを実行していて、誰かがメッセージ ボックスの 1 つだけをクリックすると、別のアプリに 2 つ目のメッセージ ボックスが表示されることがあります。私はもともと waithandle を static/shared として宣言していて、それが問題だと思っていましたが、そうではありませんでした。また、各アプリに独自の待機ハンドルを作成させ、それをベースに渡そうとしましたが、同じ結果になりました。待機ハンドルが異なるアプリケーション間で共有されているように見える理由を知っている人はいますか? ところで、waitHandle は実際には ManualResetEvent です

4

2 に答える 2

1

まず、これを複数のアプリケーションで使用する場合は、このコンストラクターEventWaitHandleを使用して名前付きを作成するか、名前付きオブジェクトを作成する他のコンストラクターのいずれかを作成する必要があります。Aは単一のプロセスでのみ機能します。ManualResetEvent

第二に、名前付きミューテックスはおそらくより良い解決策です。私が推奨したコードには競合状態があることに気付きました。スレッド A がを実行WaitOne(0)して成功し、スレッド A が を呼び出す前にスレッド B が同じことを実行するとReset、両方のスレッドがメッセージ ボックスを表示することになります。

and を使用するMutexと、WaitOne(0)その問題が解決します。Mutexただし、必ず をリリースしてください。

if (mutex.WaitOne(0))
{
    try
    {
        // do stuff
    }
    finally
    {
        mutex.ReleaseMutex();
    }
}
于 2012-12-04T05:34:25.927 に答える
0

正しく機能しなかった理由は、タイマーイベントの外で最初のメッセージボックスを表示していたというバグがあったためです。それはすべきだった:

waitHandle.Reset()
MessageBox.Show(MDIMain, "There is a recent critical deployment, please re-deploy STAR to get latest changes.", "Critical Deployment", MessageBoxButtons.OK, MessageBoxIcon.Warning)
waitHandle.Set()
于 2012-12-05T15:04:20.503 に答える