многопоточность — Borland Multithreaded TCPServer Issue

[Я могу ошибаться в этом] Сервер TIdTCPServer является многопоточным в Borland C ++ builder. Он обрабатывает все клиенты в отдельных потоках. Это написано в помощь Borland C ++.

Теперь моя проблема & вопрос.
Например, ShowMessage(String ..) метод должен вызываться в основном (графическом) потоке. Но, как я уже сказал выше, TCPServer является многопоточным и обрабатывает OnExecute событие в разных темах. Когда я использую метод ShowMessage в событии OnExecute (которое обрабатывается в потоке, отличном от основного потока), я получаю странные результаты. Иногда ShowMessage() работает, как и ожидалось, иногда он отображается без какого-либо текста на нем с разными размерами блоков (бесконечный, очень длинный, нормальный и т. д.). Другие изменения пользовательского интерфейса не вызывают проблем (обновите TEdit, TMemo. Только ShowMessage() сейчас есть проблемы)

Я думаю, что эта проблема является результатом вызова ShowMessage() метод не в главном потоке (GUI), а в потоке TCPServer, который создается для клиентских подключений внутри TIdTCPServer.
Так как я могу это исправить?

0

Решение

Все изменения в пользовательском интерфейсе должны быть сделаны в главном потоке. Вы можете использовать TThread :: Queue функция для выполнения функции в главном потоке. Он отправляет сообщение в основную очередь сообщений, и TThreadMethod, переданный в качестве параметра, выполняется, когда основной поток обрабатывает сообщения.

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

3

Другие решения

ShowMessage() отображает VCL TFormи как таковой не является потокобезопасным. Вы должны использовать TThread::Synchronize(), TThread::Queue(), TIdSync, TIdNotifyили любой другой механизм связи между потоками по вашему выбору, чтобы сделать ShowMessage() запустить на главном потоке.

Чтобы отобразить всплывающее сообщение в рабочем потоке, используйте Win32 API MessageBox() функция вместо Он является поточно-ориентированным и может вызываться в любом потоке без синхронизации с основным потоком.

5

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

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

  1. всегда исключение приложение закрыть / выйти
  2. случайное зависание / исключение приложения (фатальное или не фатальное для приложения)
  3. случайные испорченные визуальные материалы VCL (отсутствующие элементы в списках, пропущенные события и т. д.)
  4. случайное непредсказуемое поведение (иногда перезаписывает даже данные приложения, не относящиеся к VCL)

Многие случайные проблемы повторяются в зависимости от:

  • Сложность интерфейса
  • сложность исходного кода (больший код чаще возникает)
  • количество окон / форм

Также остерегайтесь утечек памяти. VCL крайне нестабилен, если менеджер памяти поврежден из-за неправильного удаления и т. Д. (Не знаю, как об этом в более новых версиях, но в bds2006 это очень большая проблема)

PS. если вам нужны только диалоги, тогда используйте интерфейс WINAPI, он должен работать даже в потоках, если ваши текстовые данные не связаны с VCL (например, доступ к переменной AnsiString — это нормально, а доступ к DBGrid — нет)

0