Я экспериментирую с повторным входом в цикл сообщений.Обратите внимание, что я не обязательно выберу написать приложение таким образом, я просто хочу уточнить мое понимание циклов сообщений.
Допустим, я запускаю открытие модального диалога с помощью ShowDialog
.Насколько я понимаю, вызов, кажется, блокируется, но на самом деле цикл сообщений был повторно введен где-то в стек вызовов, чтобы диалог оставался отзывчивым.Если бы мы не повторно входили в цикл сообщений, диалоговое окно не отображалось бы и т. Д. Таким образом, я понимаю, что ShowDialog
работает аналогично Application.DoEvents
.
.для рисования сообщений цикл сообщений также может обрабатывать другие сообщения, некоторые из которых могут выполнять обработчики событий.Эти события выполняются во время звонка на ShowDialog
.Это может сбивать с толку, потому что кажется, что случайный код выполняется во время вызова ShowDialog
, даже если код выполняется в том же потоке, что и ShowDialog
.
Допустим, я показываю диалоги ожидание ввода пользователя.В то время как я показываю это диалоговое окно, я получаю еще один звонок с просьбой о том же вводе пользователя.Я не хочу показывать другой диалог.
Если я использую переменную для записи того, запрашиваю ли я в данный момент ввод, я могу сказать, отображается ли уже мой диалог.Если это так, тогда не нужно показывать другое диалоговое окно - оно уже отображается.Я хотел бы дождаться результата первого вызова.
Ниже приведена моя попытка дождаться результата, написанного на F #.Мое ожидание реализуется путем вызова Application.DoEvents
, пока не закроется исходное диалоговое окно.Идея состоит в том, что нам нужно вызвать DoEvents
, чтобы можно было обработать щелчок ОК из формы, чтобы закрыть его.
open System
open System.Windows.Forms
let showingDialog = ref false
let lastResult = ref DialogResult.None
/// Waits for the original dialog to close.
let waitForOriginalDialogResult () =
printfn "Doing events while dialog is showing"
while !showingDialog do Application.DoEvents()
!lastResult
/// Actually shows the dialog.
let showDialog () =
printfn "Showing dialog"
use dialog = new Form()
dialog.Controls.Add(new Button(Text = "OK", DialogResult = DialogResult.OK))
lastResult := dialog.ShowDialog()
/// Either gets user input direct from a dialog, or waits for an existing dialog.
let getUserInput () =
if !showingDialog then
waitForOriginalDialogResult()
else
showingDialog := true
try showDialog() finally showingDialog := false
!lastResult
let timer = new Timer(Interval = 9999)
timer.Tick.Add(fun e -> getUserInput() |> printfn "Sub-show: %A")
timer.Start()
getUserInput() |> printfn "Main show: %A"
timer.Stop()
Если я нажму кнопку ОК до запуска таймера, диалоговое окнозакрывается нормально и все работает.На консоль выводится следующее:
Showing dialog
Main show: OK
Однако после срабатывания таймера нажатие кнопки OK больше не закрывает форму.Диалог кажется совершенно отзывчивым, но я не могу его закрыть.Alt + F4, кнопка X и кнопка OK не работают.Кнопки анимируются так, как будто они нажаты, но диалог не закрывается.Однако я могу использовать кнопки «Развернуть» и «Свернуть», а также изменить размер формы.
Я бы подумал, что вызов DoEvents
поднимет сообщение о щелчке ОК или закрытии и закроет форму.Почему не работают кнопки закрытия?
Во-вторых, есть ли способ выполнить такое ожидание, которое работает?