我有一个非常讨厌的问题,我正试图找到最简单的解决方案,但我似乎一直在使它复杂化。
我的程序使用ShowDialog函数显示一个自定义对话框(我使用New构造函数创建此表单),但是当我的程序在对话框中等待输入时,我的程序继续运行其他代码,(我假设已启动从其他消息,但我仍然无法找到关于此的良好信息,所以除了这个主题,任何人都有关于此的参考),并到达同一点,在那里显示对话框并显示它。所以我最终得到了大量的对话框。
我的目标是防止过多的对话框。如果程序到达此对话框启动点,我希望它等待/暂停,直到第一个对话框完成。
我考虑过线程解决方案,后台工作者,各种想法,但它们似乎使事情变得复杂,我实际上并没有修复它。
有谁知道如何防止这种情况发生?
非常感谢您的帮助。 感谢
答案 0 :(得分:1)
在我看来,你的代码中有一些非常难看的bug!我首先关注修复这个bug。执行此操作的简单方法是在打开对话框的行上设置断点。第二次点击该行时(第一个对话框仍处于打开状态),查看该点的堆栈跟踪并检查所有活动线程(查看线程和查看堆栈窗口)以找出问题的原因。
此外,更改代码以打开模式对话框窗口,其中父窗口必须是所有者。模态对话框窗口将停止执行并阻止父窗口处理用户输入(这可能导致此行为)。
从您的评论中我收集到您有几个无法控制的线程,并且您希望一次一个线程来访问消息框代码。使用线程时,有几个可用的同步原语。扩展每一本书都需要一本书(你可以尝试Concurrent Programming on Windows,一本书在其结构中有一些缺陷时是彻底的),知道正确的一本书需要你的代码知识。
也就是说,你可能希望做一些类似下面的事情,使用一个至少阻止其他线程访问代码的Mutex(意思是:它会将它们置于挂起状态直到Mutex被释放)。如果要阻止弹出框多次显示,请添加一个静态布尔标志变量(或在弹出窗体“仅显示一次”上添加一个复选框)。 Mutex plus flag解决了两个问题:只有一个线程会运行该代码,代码只会运行一次。
// as static class variable, create a mutex
private static Mutex dialogMutex = new Mutex();
// a static flag preventing the dialog box to show more than once
// (you may wish to resolve this differently, depending on req's)
private static boolean dialogIsShownOnce = false;
public static void ShowDialogBox()
{
// Wait until it is safe to enter, this makes the current thread
// the exclusive user of this code and other threads may only enter
// after the current thread finishes.
dialogMutex.WaitOne();
// depending on your requirements, you may not want this
// must come _after_ WaitOne to prevent entering before another
// thread that entered hasn't yet changed this variable
if(dialogIsShownOnce)
return;
// show your dialog box as a modal box
// if you are unsure: add a breakpoint just after the ShowDialog
// it should only be hit _after_ you dismiss the dialog box
yourForm.ShowDialog();
// set the flag, or the counter, or whatever you wish:
dialogIsShownOnce = true;
// Release the Mutex, this will remove the "roadblock" and allow
// other threads to enter this piece of code
dialogMutex.ReleaseMutex();
}
上面的代码未经过测试,应该被视为如何解决此问题的提示。有很多方法可以解决这个问题,但我认为上述方法可能正是您所需要的。
答案 1 :(得分:1)
我可能在这里误解了这个问题,但您是否尝试过以下方法:
Dim frmFindForm As dlgPromptForm
frmFindForm = New dlgPromptForm()
If (frmFindForm.ShowDialog(Me) = DialogResult.OK) Then
'Do something because they hit ok, if needed
Else
'Do something else because they didn't hit ok, if needed
End If`
要使其工作,您需要确保当用户点击按钮时,对话框窗体设置DialogResult属性。 (例如:单击“确定”按钮,单击“DialogResult = System.Windows.Forms.DialogResult.OK”)
这会导致程序停在if,直到用户按下对话框上的其中一个按钮。
这可能与您所寻找的内容有关,但我真的无法从您提供的信息中得知。
答案 2 :(得分:0)
我会看到两种可能性: 如果您在一个位置打开对话框,而不是在那里更改它不会调用对话框,而是某种堆栈,并且您可以检查对话框何时关闭,如果堆栈上还有剩余的东西。
或者,如果可能,在打开第一个对话框时更改所有者窗口,该窗口将传递给对话框。并隐藏。 如果所有者被隐藏 - >对话框被隐藏。
答案 3 :(得分:0)
在关闭对话框之前,使用ShowDialog()绝不应该让其余的代码执行。所以,我的猜测是您的代码存在问题。正如Abel建议的那样,您应该使用断点并跟踪代码。 我的另一个猜测是,其他对话框是从原始对话框中启动的,并且它会以递归方式继续发生。
如果您在此处发布代码,将会更容易提供帮助。
答案 4 :(得分:0)
我只想创建一个表单范围boolean say
DIM DisplayedMSGBOX as boolean = false
(如果线程在单独的表单上运行,只需将此布尔值设为全局)
public DisplayedMSGBOX as boolean = false)
然后在显示消息框的位置我会放置
如果没有显示MSGBOX那么
msgbox(“这将是你的msgbox”)
ENDIF
在某些时候,如果你想重置msgbox再次使用
DisplayedMSGBOX = false
现在重置了msgbox。
答案 5 :(得分:0)
是的,这可能来自您的代码,正如Abel所建议的那样,但也有一个非常愚蠢的Visual Studio Designer错误,这也会导致只需单击即可打开双重甚至三个对话框。
您知道如何双击Visual Studio Designer中的元素或按钮,它会在代码中为它创建一个空子(如果没有找到现有代码)?嗯,在Visual Studio / Basic中有一个非常恼人的错误,双击一个新按钮(有时)不会创建一个新的子按钮,而是随意且莫名其妙地将该按钮的点击事件粘贴到现有的潜艇上,而无需您的意愿或同意。如果你不注意并忘记删除垃圾点击事件,你最终会意外地同时启动几个潜艇。
我在以下项目中有一个例子:
Private Sub btnOptionsThemeLB_HK_Click(sender As System.Object, e As System.EventArgs) Handles btnOptionsThemeLB_HK.Click, btnOptionsThemeLB_Back2.Click, btnOptionsThemeLB_Back5.Click, btnOptionsThemeLB_Back4.Click
ColorMeNow.Color = tempOptionsThemeLB_HK
ColorMeNow.ShowDialog()
Me.btnOptionsThemeLB_HK.BackColor = ColorMeNow.Color
txtbOptionsThemeLB_HK_Red.Text = exRed(ColorMeNow.Color).ToString
txtbOptionsThemeLB_HK_Green.Text = exGreen(ColorMeNow.Color).ToString
txtbOptionsThemeLB_HK_Blue.Text = exBlue(ColorMeNow.Color).ToString
txtbOptionsThemeLB_HK_Hex.Text = exHexFromColor(ColorMeNow.Color)
tempOptionsThemeLB_HK = ColorMeNow.Color
'My.Settings.Save()
End Sub
这里的罪魁祸首可以在子申报行中找到。
我应该有:
Private Sub ... Handles btnOptionsThemeLB_HK.Click
但相反,我有:
Private Sub ... Handles btnOptionsThemeLB_HK.Click, btnOptionsThemeLB_Back2.Click, btnOptionsThemeLB_Back5.Click, btnOptionsThemeLB_Back4.Click
所有这些子开放颜色选择器对话。 Back2,Back4和Back5被设计师自动添加到Sub btnOptionsThemeLB_HK_Click,我忘了删除它们。在运行时,当我单击Back2,Back4和Back5按钮时,它们产生了两个对话框(属于它们的对话框和btnOptionsThemeLB_HK_Click的对话框)。删除不需要的点击事件将解决此问题。
更新: 似乎如果您想通过拖动和复制现有按钮来添加新按钮,并且如果正在复制的现有按钮已经与现有Sub关联,则Visual Basic将假设您希望复制它的点击事件,并为您复制的每个按钮添加一个新的点击事件给所述Sub。