Question

Based upon this question i decided to try to use waithandles/eventwaithandle for my solution based upon Jim Mischel recommendation. I "almost" have it working. Here is the code

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

Again this is from a base form that pretty much all our applications inherit from. When we are using a single app it works perfectly. If your running multiple apps that inherit from the base form and someone clicks just one of the message boxes sometimes a second message box will display in another app. I originally had waithandle declared as static/shared and thought that was the problem but it wasn't. I also tried to have each app create its own waithandle and pass it into the base and it resulted in the same affect. Does anyone have an idea why it appears the waithandle is being shared between different applications? Oh by the way, waitHandle is actually a ManualResetEvent

Was it helpful?

Solution

First, if you want to use this across multiple applications, you'll have to create a named EventWaitHandle using this constructor, or one of the others that creates a named object. A ManualResetEvent will only work for a single process.

Second, a named Mutex is probably a better solution. I just realized that the code I recommended has a race condition. If Thread A does the WaitOne(0) and it succeeds, and then Thread B comes along and does the same thing before Thread A can call Reset, then both threads will end up displaying the message box.

Using a Mutex and WaitOne(0) will solve that problem. Be sure to release the Mutex, though:

if (mutex.WaitOne(0))
{
    try
    {
        // do stuff
    }
    finally
    {
        mutex.ReleaseMutex();
    }
}

OTHER TIPS

The reason it wasn't work correctly is that i had a bug where i was showing the first message box outside of the timer event. It should have been:

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()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top