После прогулки я понял, что происходит.
Вот мое объяснение идея о том, что не так с кодом (или причина, по которой вопрос был опубликован).
Button_Click
выполняется в потоке Dispatcher
. Поток Dispatcher
, как я знаю, является единственным для окна и его дочерних элементов.
Даже если Button_Click
занимает больше секунды (достаточно долго), и пользователю удается снова нажать кнопку (или каким-либо другим образом взаимодействовать с пользовательским интерфейсом), следующий Button_Click
(или другой соответствующий обработчик) не выполняется немедленно , но помещается в очередь диспетчеризации .
Dispatcher.Invoke
выполняет делегат в потоке пользовательского интерфейса. Invoke
, я полагаю, отправляет сообщение в цикл делегата GetMessage()
и блокирует вызывающий поток, пока сообщение не завершится.
Я ожидал, что делегат начнет выполнение только после выхода из Button_Click
.
MessageBox.Show()
- это блокирующий вызов. Следующая инструкция не будет выполнена, пока пользователь не нажмет «ОК».
На самом деле происходит то, что Диспетчер фактически различает разные окна и знает, что Button_Click
вызвал модальное диалоговое окно, и поэтому любое взаимодействие с окном должно издавать звуковой сигнал, а окно сообщения должно мигать.
Но продолжает отправлять сообщения. В конце концов, именно поэтому все щелчки пользователей преобразуются в сообщения Button.Click, и окно сообщений закрывается.
Вот почему вызванный делегат выполняется до выхода Button_Click
.
Вызванный делегат разбивается на Button_Click
.
P.S. Как видно из кода, делегат также вызывает MessageBox.Show()
. Это приводит к новому окну сообщения , которое является модальным к предыдущему. Я заметил, что не могу нажать «Ok» в «Прямом» msgBox, прежде чем «Вызвать».