Теперь моя проблема & вопрос.
Например, ShowMessage(String ..)
метод должен вызываться в основном (графическом) потоке. Но, как я уже сказал выше, TCPServer является многопоточным и обрабатывает OnExecute
событие в разных темах. Когда я использую метод ShowMessage в событии OnExecute (которое обрабатывается в потоке, отличном от основного потока), я получаю странные результаты. Иногда ShowMessage()
работает, как и ожидалось, иногда он отображается без какого-либо текста на нем с разными размерами блоков (бесконечный, очень длинный, нормальный и т. д.). Другие изменения пользовательского интерфейса не вызывают проблем (обновите TEdit, TMemo. Только ShowMessage()
сейчас есть проблемы)
Я думаю, что эта проблема является результатом вызова ShowMessage()
метод не в главном потоке (GUI), а в потоке TCPServer, который создается для клиентских подключений внутри TIdTCPServer.
Так как я могу это исправить?
Все изменения в пользовательском интерфейсе должны быть сделаны в главном потоке. Вы можете использовать TThread :: Queue функция для выполнения функции в главном потоке. Он отправляет сообщение в основную очередь сообщений, и TThreadMethod, переданный в качестве параметра, выполняется, когда основной поток обрабатывает сообщения.
Если вам нужно передать данные в основной поток, например, чтобы показать сообщение, вам придется сделать это отдельно, так как параметры функции не могут быть переданы через функцию очереди.
ShowMessage()
отображает VCL TForm
и как таковой не является потокобезопасным. Вы должны использовать TThread::Synchronize()
, TThread::Queue()
, TIdSync
, TIdNotify
или любой другой механизм связи между потоками по вашему выбору, чтобы сделать ShowMessage()
запустить на главном потоке.
Чтобы отобразить всплывающее сообщение в рабочем потоке, используйте Win32 API MessageBox()
функция вместо Он является поточно-ориентированным и может вызываться в любом потоке без синхронизации с основным потоком.
Да, ваша проблема, скорее всего, не имеет ничего общего с TCP. любой VCL доступ должен быть сделано в основной теме. (не забывайте, что диалоги сообщений часто вызываются из оболочек VCL, а не напрямую через winapi)
Да, я знаю, что иногда это работает «хорошо», даже когда нет, но тогда возникают следующие проблемы:
Многие случайные проблемы повторяются в зависимости от:
Также остерегайтесь утечек памяти. VCL крайне нестабилен, если менеджер памяти поврежден из-за неправильного удаления и т. Д. (Не знаю, как об этом в более новых версиях, но в bds2006 это очень большая проблема)
PS. если вам нужны только диалоги, тогда используйте интерфейс WINAPI, он должен работать даже в потоках, если ваши текстовые данные не связаны с VCL (например, доступ к переменной AnsiString — это нормально, а доступ к DBGrid — нет)