Несколько процессов и ручек ожидания

Основываясь на этом вопросе, я решил попробовать использовать 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

Опять же, это базовая форма, от которой наследуются практически все наши приложения. Когда мы используем одно приложение, оно отлично работает. Если вы запускаете несколько приложений, которые наследуют от базовой формы, и кто-то щелкает только одно из окон сообщения, иногда в другом приложении будет отображаться второе окно сообщения. Первоначально я ждал, что waithandle объявлен как static / shared, и подумал, что это проблема, но это не так. Я также попытался заставить каждое приложение создать свою собственную ручку ожидания и передать ее в базу, и это привело к тому же эффекту. У кого-нибудь есть идея, почему кажется, что ручка ожидания используется совместно различными приложениями? О, кстати, waitHandle на самом деле является ManualResetEvent

2 ответа

Решение

Во-первых, если вы хотите использовать это в нескольких приложениях, вам придется создать именованный EventWaitHandle используя этот конструктор или один из других, который создает именованный объект. ManualResetEvent будет работать только для одного процесса.

Во-вторых, названный Mutex, вероятно, является лучшим решением. Я только что понял, что код, который я рекомендовал, имеет состояние гонки. Если поток А делает WaitOne(0) и это успешно, а затем поток B приходит и делает то же самое, прежде чем поток A может вызвать Reset, тогда обе темы будут в конечном итоге отображать окно сообщения.

Используя Mutex а также WaitOne(0) решит эту проблему. Обязательно выпустите Mutex, хоть:

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

Причина, по которой это не сработало правильно, в том, что у меня была ошибка, когда я показывал первое окно сообщения вне события таймера. Это должно было быть:

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()
Другие вопросы по тегам