Как я могу прекратить QThread

Недавно я столкнулся с этой проблемой, как я упоминал в этом заголовке. Я попытался с помощью QThread::terminate(), но я просто не могу остановить поток, который находится в мертвом цикле (скажем, в то время как (1)).

большое спасибо.

5 ответов

Завершение потока - это простое решение для остановки асинхронной операции, но обычно это плохая идея: поток может выполнять системный вызов или может обновлять структуру данных после завершения, что может привести к выходу из программы. или даже ОС в нестабильном состоянии.

Попробуйте преобразовать while(1) в while( isAlive()) и заставить isAlive () возвращать false, когда вы хотите, чтобы поток завершился.

QThreads могут зайти в тупик, если они закончатся "естественно" во время завершения.

Например, в Unix, если поток ожидает вызова read, попытка завершения (сигнал Unix) прервет вызов read с кодом ошибки перед уничтожением потока.

Это означает, что поток все еще может достигать своей естественной точки выхода, будучи завершенным. Когда это происходит, достигается тупик, поскольку некоторый внутренний мьютекс уже заблокирован вызовом terminate.

Мой обходной путь - убедиться, что поток никогда не вернется, если он был прерван.

while( read(...) > 0 ) {

  // Do stuff...
}

while( wasTerminated )
  sleep(1);

return;

wasTerolved здесь на самом деле реализован немного сложнее, с использованием атомарных целых:

enum {

  Running, Terminating, Quitting
};

QAtomicInt _state; // Initialized to Running

void myTerminate()
{
  if( _state.testAndSetAquire(Running, Terminating) )
    terminate();
}

void run()
{
  [...]

  while(read(...) > 0 ) {

    [...]
  }

  if( !_state.testAndSetAquire(Running, Quitting) ) {
    for(;;) sleep(1);
  }
}

Вы пытались выйти или выйти?

Звонил ли поток QThread::setTerminationEnabled(false)? Это может привести к задержке завершения потока на неопределенный срок.

РЕДАКТИРОВАТЬ: Я не знаю, на какой платформе вы находитесь, но я проверил реализацию QThread::terminate для Windows. Предполагая, что поток на самом деле запущен с самого начала, и завершение не было отключено с помощью вышеуказанной функции, это в основном оболочка TerminateThread() в Windows API. Эта функция принимает неуважение ни от какого потока и имеет тенденцию оставлять беспорядок с утечками ресурсов и подобным висячим состоянием. Если это не убивает поток, вы либо имеете дело с вызовами ядра зомби (скорее всего, заблокирован ввод / вывод), либо у вас есть где-то еще большие проблемы.

Использовать безымянные трубы

int gPipeFdTest[2];  //create a global integer array

Когда вы собираетесь создавать трубы, используйте

if( pipe(gPipeFdTest) < 0)

{

perror("Pipe failed");

exit(1);

}

Приведенный выше код создаст канал с двумя концами gPipeFdTest[0] для чтения и gPipeFdTest[1] для записи. Что вы можете сделать, так это настроить свою функцию run на чтение канала с помощью системного вызова select. И откуда вы хотите выйти из строя, там настроено писать с помощью записи системного вызова. Я использовал системный вызов select для мониторинга конца чтения канала, так как он подходит для моей реализации. Попробуй разобраться во всем этом в твоем случае. Если вам нужна дополнительная помощь, дайте мне знать.

Редактировать:

Моя проблема была такой же, как ваша. У меня был цикл while(1), и другие вещи, которые я пробовал, требовали мьютексов и других необычных многопоточных mumbo jumbo, что добавляло сложность, а отладка была кошмаром. Использование каналов избавило меня от этих сложностей, а также упростило код. Я не говорю, что это лучший вариант, но в моем случае это была лучшая и самая чистая альтернатива. Я прослушал мое зависшее приложение перед этим решением.

Другие вопросы по тегам