Как остановить отображение нескольких диалоговых окон? - PullRequest
5 голосов
/ 14 июля 2010

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

Моя программа отображает настраиваемое диалоговое окно, используя функцию ShowDialog (я создаю этоформы с использованием конструктора New), но пока моя программа ожидает ввода в диалоговом окне, моя программа продолжает выполнять другой код (я предполагаю, что инициируется из других сообщений, но я все еще не могу найти хорошую информацию по этому вопросу, так чтоПомимо этой темы у кого-нибудь есть ссылка на это), и он приходит к той же точке, где должно отображаться диалоговое окно, и отображает ее.В итоге я получаю множество диалоговых окон.

Моя цель - предотвратить чрезмерное количество диалоговых окон.Если программа прибывает в эту точку инициализации диалога, я бы хотел подождать / сделать паузу, пока не закончится первое диалоговое окно.

Я думал о многопоточных решениях, фоновых работниках, всевозможных идеях, но они просто усложняютвещи, и я на самом деле это не исправил.

Кто-нибудь есть идеи, как я мог бы предотвратить это?

Ваша помощь очень ценится.Спасибо

Ответы [ 6 ]

1 голос
/ 16 июля 2010

Я мог бы неправильно понять проблему здесь, но вы пробовали следующее:

 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, пока пользователь не нажмет одну из кнопок в диалоговом окне.

Опять же, это может отличаться от того, что вы ищете, но я действительно не могу судить по предоставленной вами информации.

1 голос
/ 14 июля 2010

Мне кажется, что в вашем коде есть какая-то ужасная ошибка! Я бы сосредоточился на исправлении этой ошибки в первую очередь. Самый простой способ сделать это - установить точку останова на линии, которая открывает диалог. Когда линия нажата во второй раз (пока первое диалоговое окно все еще открыто), просмотрите трассировку стека в этой точке и проверьте все активные потоки (окна Просмотр потоков и Просмотр стека) на предмет причины проблемы.

Кроме того, измените код, чтобы вместо этого открыть модальное диалоговое окно, где родительское окно должно быть владельцем. Модальное диалоговое окно остановит выполнение и не позволит родительскому окну обрабатывать пользовательский ввод (что могло привести к такому поведению).

Редактировать

Из ваших комментариев я понял, что у вас есть несколько потоков, которыми вы не можете управлять, и что вы хотите, чтобы по одному потоку за раз осуществлялся доступ к коду сообщения. При работе с потоками доступно несколько примитивов синхронизации. Для раскрытия каждого из них требуется книга (вы можете попробовать Параллельное программирование в Windows , которая является исчерпывающей, хотя у книги есть некоторые недостатки в своей структуре), для того, чтобы узнать, какой из них вам нужен, требуется знание вашего кода.

Тем не менее, вы можете захотеть сделать что-то вроде следующего, используя Mutex, который по крайней мере запрещает другим потокам доступ к коду (то есть: он переводит их в состояние приостановки до тех пор, пока Mutex не будет выпущен). Добавьте статическую переменную логического флага (или установите флажок во всплывающей форме «Показывать только один раз»), если вы хотите, чтобы всплывающее окно отображалось более одного раза. Флаг Mutex plus решает две проблемы в одной: только один поток будет выполнять этот код, а код будет выполняться только один раз, когда-либо.

// 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();
}

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

0 голосов
/ 21 июня 2017

Да, это может исходить из вашего кода, как предположил Абель, но есть и очень глупая ошибка 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 для каждой дублируемой кнопки.

0 голосов
/ 01 сентября 2010

Я бы просто создал логическую область видимости формы, скажем

DIM Отображается MSGBOX как логическое = false

(Если потоки выполняются в отдельной форме, просто сделайте этот логический глобальный тип)

public Displayed MSGBOX как логическое = false)

, а затем в точке, где отображается окно сообщения, я бы поместил

ЕСЛИ не отображается MSGBOEN THEN

msgbox ("Thisбудет вашим сообщением msgbox ")

ENDIF

В какой-то момент, если вы хотите сбросить msgbox для использования снова, просто

DisplayedMSGBOX = false

и теперьmsgbox сбрасывается.

0 голосов
/ 19 июля 2010

Использование ShowDialog () никогда не должно позволять выполнению остальной части кода до закрытия диалога.Итак, я думаю, что есть проблема с вашим кодом.Как рекомендовал Абель, вы должны использовать точку останова и отслеживать свой код.Мое другое предположение состоит в том, что другие диалоговые окна запускаются из исходного диалогового окна, и это продолжает происходить рекурсивно.

Было бы легче помочь, если вы разместите свой код здесь.

0 голосов
/ 14 июля 2010

я бы увидел 2 варианта: если у вас открыто диалоговое окно в одной позиции, измените его так, чтобы оно вызывало не диалоговое окно, а какой-то стек, и вы можете проверить, когда диалоговое окно закрыто, если в стеке осталось что-то.

или вы изменяете, когда открываете первое диалоговое окно, окно владельца, которое передается диалоговому окну, если это возможно. и скрыть это. если владелец скрыт -> диалоговое окно скрыто.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...