基于这个问题,我决定根据 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
同样,这是来自几乎所有应用程序继承的基本形式。当我们使用单个应用程序时,它可以完美运行。如果您运行的多个应用继承自基本窗体,并且有人只单击其中一个消息框,则有时另一个消息框将显示在另一个应用中。我最初将等待句柄声明为静态/共享,并认为这是问题所在,但事实并非如此。我还尝试让每个应用程序创建自己的等待句柄并将其传递到基础中,这导致了相同的影响。有没有人知道为什么等待句柄似乎在不同的应用程序之间共享?哦,顺便说一下,waitHandle实际上是一个手动重置事件
首先,如果要在多个应用程序中使用它,则必须使用此构造函数创建一个命名EventWaitHandle
,或者创建命名对象的其他构造函数之一。ManualResetEvent
仅适用于单个进程。
其次,命名的互斥体可能是一个更好的解决方案。我刚刚意识到我推荐的代码具有竞争条件。如果线程 A 执行WaitOne(0)
并且成功,然后线程 B 出现并在线程 A 可以调用 Reset
之前执行相同的操作,则两个线程最终都会显示消息框。
使用Mutex
和WaitOne(0)
将解决这个问题。不过,请务必发布Mutex
:
if (mutex.WaitOne(0))
{
try
{
// do stuff
}
finally
{
mutex.ReleaseMutex();
}
}
<</div>
div class="one_answers"> 它无法正常工作的原因是我有一个错误,我在计时器事件之外显示第一个消息框。它应该是:
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()