QThread и QTcpSocket
Я сделал серьезную ошибку, когда делал какой-то проект, и теперь мне нужно перепрограммировать его снизу. Я пишу многопоточный сервер, который будет обрабатывать соединения, запросы и т. Д. Но, когда я создал новый класс с базой Объект QThread, я запускал поток с QThread->run(), а не QThread->start(). Теперь я получаю кучу ошибок. Здесь ситуация. У меня есть сервер, который создает новые потоки на каждом соединении и начинает считывать данные с каждого подключенного клиента. Когда я получаю данные, он испускает сигналы, которые подключены к основному классу графического интерфейса пользователя, и отображает результат OK. Он также сохраняет дескриптор сокета для ответа на сообщения. Когда я записываю данные в сокет из класса GUI, он говорит это:
QObject: Невозможно создать дочерние элементы для родителя, который находится в другом потоке. (Родитель - QNativeSocketEngine(0x23a6c38), родительский поток - MyThread(0x1fb8670), текущий поток - QThread(0x9eb980).
В чем дело?
1 ответ
Я знаю QT, но не очень хорошо знаком с самой реализацией сокета QT, но из звука вашего сообщения об ошибке и из-за того, как вы описываете свой дизайн, ваша проблема связана не с QT, а с архитектурой потоков / сокетов в целом. Многопоточные приложения требуют тщательного продуманного интеллектуального проектирования, чтобы быть эффективными и гарантировать, что ваши данные сеанса и т. Д. Согласованы и не чреваты проблемами параллелизма, потерянными структурами данных и т. Д.
Он также сохраняет дескриптор сокета для ответа на сообщения. Когда я записываю данные в сокет из класса GUI, он говорит это...:
Не зная всех деталей вашей реализации, если вы сохранили дескриптор сокета в потоке 1 для ответа на вызов в потоке 1, а затем попытались записать в него данные из вызова с использованием потока 2, этот оригинальный дескриптор сокета недопустим в контекст темы 2. Это может объяснить ваше сообщение об ошибке.
Сохранение дескриптора сокета для последующих вызовов не является хорошим способом сделать что-либо по ряду причин (включая проблему, с которой вы столкнулись.) Почему вы это делаете? Если вам необходимо сохранить информацию о клиенте при вызовах, используйте структуры сеансов для сохранения этих данных. Если вы хотите, чтобы весь поток оставался живым, пока разговор продолжается, спроектируйте взаимодействия потоков / сокетов таким образом, чтобы они учитывали пул потоков и т. Д. Но у вас не должно быть просто потерянных сокетов - каждый должен существовать в имеет собственный контекст потока и не имеет действительного дескриптора вне своего "домашнего" потока.
Когда сокет завершает свой диалог, поток, который был создан, и сокет, созданный в этом потоке для продолжения диалога, ГОТОВ - все должно быть очищено.
Если я правильно понимаю вашу реализацию, мои предложения должны решить вашу проблему.
В своем комментарии вы упоминаете:
"сокет как глобальная переменная" - вы НЕ должны использовать глобальный сокет таким образом, если я правильно понимаю, что вы делаете.
В вашем серверном приложении должен быть основной поток с постоянным сокетом, который прослушивает запросы. Когда вы получаете входящий запрос, должен исходить сигнал, а слот для этого сигнала должен порождать поток, который инициализирует новый сокет для обработки этого запроса. Обработайте запрос в ветке, затем все почистите и т. Д.
Если вам нужно извлечь информацию из входящих запросов и сохранить ее где-нибудь, сделайте это в основном потоке, и другие потоки не должны иметь доступа к структурам, которые вы используете для сохранения этого сеанса в основном потоке (если вы не используете механизмы синхронизации). То же самое если вы хотите получить информацию из обработки запроса, когда она будет завершена - верните ее из порожденного потока в основной поток с помощью сигнала, генерируемого, когда поток завершается.
Если вы не следуете этим правилам, вам нужно использовать объекты синхронизации, или у вас возникнут всевозможные проблемы, в том числе то, что вы испытываете, судя по звуку вашего сообщения об ошибке.
Короче говоря: "Что происходит в потоке, остается в потоке"