Я использую Qt 4.8.6, MS Visual Studio 2008, Windows 7. Я создал программу с графическим интерфейсом. Он содержит основной поток GUI и рабочий поток (я не сделал QThread
подкласс, кстати), который делает синхронные вызовы сторонних функций DLL. Эти функции довольно медленные. QTcpServer
экземпляр также находится под рабочим потоком. Мой рабочий класс содержит QTcpServer
и методы оболочки DLL.
я знаю это quit()
предпочтительнее terminate()
, но я не хочу ждать минуты (из-за медленных функций DLL) во время завершения работы программы. Когда я пытаюсь terminate()
рабочий поток, замечаю предупреждения об остановке QTcpServer
из другого потока. Как правильно отключить процесс?
Если для этого нет основополагающей причины, вы не должны пытаться завершать потоки пользовательским кодом при завершении процесса.
Если такой причины нет, просто вызовите системный вызов завершения процесса ОС, например. ExitProcess (0). ОС может и будет останавливать все потоки процесса в любом состоянии, прежде чем освободить все ресурсы процесса. Пользовательский код не может этого сделать и не должен пытаться завершать потоки или сигнализировать их о прекращении работы, если в этом нет крайней необходимости.
Попытка «очистить» с помощью пользовательского кода звучит «приятно» (по-видимому), но это дорогая роскошь, за которую вы заплатите дополнительным кодом, дополнительным тестированием и дополнительным обслуживанием.
То есть, если ваши клиенты не перестают покупать ваше приложение, потому что они разозлились из-за того, что оно закрывается.
ОС очень хороша для остановки потоков и очистки. Это были бесконечные тысячи часов тестирования во время разработки и десятилетия жизни в дикой природе, где проблемы с завершением процесса стали бы явными и исправленными. Вы даже не приблизитесь к этому с вашими флагами, событиями и т. Д., Поскольку вы пытаетесь остановить потоки, работающие на другом ядре, без использования драйвера межпроцессора.
В некоторых случаях вам придется прибегать к пользовательскому коду для остановки потоков. Если вам нужно остановить их до завершения процесса, или вам нужно закрыть какое-то соединение с БД, сбросить какой-то файл при завершении работы, устранить проблемы с межпроцессорным обменом данными или другие подобные проблемы, вам придется прибегнуть к некоторым из подходов, уже предложенных в других ответах. ,
Если нет, не пытайтесь дублировать функциональность ОС во имя «милости». Просто попросите его прекратить ваш процесс. Вы можете получить теплое нечеткое чувство, когда ваше приложение мгновенно завершает работу, в то время как другие разработчики все еще пытаются внедрить индикаторы выполнения «Завершение работы» или пытаются объяснить клиентам, почему у них все еще работают 15 приложений-зомби.
QThread::quit
говорит циклу обработки потока выйти. После его вызова поток завершится, как только элемент управления вернется в цикл обработки потока.
Вы также можете принудительно завершить поток прямо сейчас через QThread::terminate()
, но это очень плохая практика, потому что это может завершить поток в неопределенной позиции в его коде, что означает, что вы можете получить ресурсы, которые никогда не освободятся, и другие неприятные вещи. Так что используйте это, только если вы действительно не можете обойти это.
Поэтому я думаю, что правильный подход — сначала сказать потоку, что он должен нормально завершиться, и если что-то пойдет не так и займет много времени, а у вас нет возможности его дождаться, затем прекратите его:
QThread * th = myWorkerObject->thread();
th->quit();
th->wait(5000); // Wait for some seconds to quit
if(th->isRunning()) // Something took time more than usual, I have to terminate it
th->terminate();
Вы всегда должны стараться не убивать темы извне силой и вместо этого просить их красиво закончить то, что они делают. Обычно это означает, что поток регулярно проверяет, должен ли он завершить себя, и внешний мир говорит ему, что он должен завершиться, когда это необходимо (путем установки флага, сигнализации о событии или чего-либо, что подходит для рассматриваемой ситуации).
Когда поток просят завершить себя, он завершает то, что он делает, и существует чисто. Приложение ожидает завершения потока и затем завершает работу.
Вы говорите, что в вашем случае поток занимает много времени, чтобы закончить. Вы можете принять это во внимание и по-прежнему завершать поток «хорошим способом» (например, вы можете скрыть окно приложения и создать впечатление, что приложение закрылось, даже если процесс занимает немного больше времени, прежде чем оно окончательно завершается; или пользователь может показать некоторую форму индикации прогресса, сообщив ему, что приложение закрывается).