Delphi - приложение зависает, пока ShowMessage или MessageDlg

почему приложение зависает при выполнении потока, и этот поток имеет ShowMessage или MessageDlg, но при использовании MessageBox все работает нормально.

все это происходило если Внешний вид приложения не дефолтный >> "Windows"

если выбран внешний вид "Windows", он никогда не будет зависать даже с ShowMessage и MessageDlg


person RepeatUntil    schedule 03.11.2014    source источник
comment
Если вы хотите получить помощь по этому вопросу, вы должны предоставить пример кода для воспроизведения проблемы.   -  person RRUZ    schedule 03.11.2014
comment
Потоки, отличные от основного потока, не должны иметь доступ к пользовательскому интерфейсу. Какой в ​​этом смысл? Если поток должен останавливаться для ввода данных пользователем, нет смысла выделять его в отдельный поток. (И использование ShowMessage или MessageDlg из потока нарушает правила запрета доступа к визуальным элементам управления, кроме основных правил потока. MessageBox не нарушает, потому что это вызов функции WinAPI, и, следовательно, он не обращается к элементам управления VCL.)   -  person Ken White    schedule 03.11.2014
comment
Что произойдет, если вы покажете модальный диалог из потока и один из основного потока? Или один из нескольких рабочих потоков? Как вы думаете, что тогда происходит?   -  person David Heffernan    schedule 03.11.2014


Ответы (1)


ShowMessage() и MessageDlg() не являются потокобезопасными. Они отображают формы VCL, которые можно использовать только в контексте основного потока пользовательского интерфейса.

Windows.MessageBox() обычно является потокобезопасным, если вы указываете нулевое окно владельца при вызове его из рабочего потока. Он создает и отображает собственное диалоговое окно и запускает собственный цикл модальных сообщений в контексте вызывающего потока, поэтому обычно проблем с потоками не возникает. Но есть некоторые подводные камни (см. эту статью: MessageBoxes и рабочие потоки).

TApplication.MessageBox() вызывает Windows.MessageBox() внутренне, но не является потокобезопасным, потому что он делает вещи, вызывающие RTL и MainForm, которые не являются потокобезопасными, и поэтому их также следует использовать только в контексте основного потока пользовательского интерфейса.

Короче говоря, не используйте всплывающие сообщения VCL в рабочих потоках — и точка. Используйте Windows.MessageBox() или, чтобы быть в безопасности, делегируйте всплывающие сообщения в основной поток пользовательского интерфейса.

person Remy Lebeau    schedule 03.11.2014