2009-12-14 2 views
15

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

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

+0

Retagged добавить более общий "Qt" тег. – ChrisV

+2

Qt doc говорит: «Предупреждение: эта функция опасна и ее использование не рекомендуется. Поток может быть завершен в любой точке его кодового пути. Потоки могут быть прерваны при изменении данных. Нет возможности для очистки потока после сам, разблокировать любые удерживаемые мьютексы и т. д. Короче говоря, используйте эту функцию только в случае крайней необходимости. Прекращение может быть явно включено или отключено, вызвав QThread :: setTerminationEnabled(). Вызов этой функции при отключении прерывания приводит к отсрочке завершения, пока окончание не будет включено ». –

ответ

0

Вы пробовали exit или quit?

+0

quote from QT help doc: «Эта функция ничего не делает, если поток не имеет цикла событий» Это может сработать в случае цикла событий. Но если я хочу закончить его, прежде чем поток завершит свою работу, как мне это сделать? большое спасибо. Дорогой. – user230938

+0

Фактически эти 2 функции фактически используются для возврата из цикла событий при вызове exec. –

0

Был ли поток называть QThread::setTerminationEnabled(false)? Это приведет к бесконечной задержке потока.

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

+0

Нет, и я уверен, что поток может быть прерван. Спасибо. – user230938

+0

и я вызываю вызов setTerminationEnabled (true); – user230938

12

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

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

+0

Привет, rpg. Пример while (1) - это всего лишь один случай. Я действительно хочу закончить поток, который делает тяжелые вычисления, которые продлится очень долго. Я просто хочу остановить его, пока он не закончит изгнание. Благодарю. ps: Я видел ключ, который Rocknroll дает --use pipe, чтобы остановить Qthread. Но я никогда не нахожу решение. – user230938

+0

Попробуйте добавить что-то похожее на точки прерывания вашей тяжелой вычислительной функции: http://www.justsoftwaresolutions.co.uk/threading/thread-interruption-in-boost-thread-library.html – rpg

+0

Да, я согласен с тем, что сказано Вот. Прекратить нить на жестком пути никогда не бывает хорошо. –

0

Чтобы использовать неназванные трубы

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

В качестве, когда, где вы собираетесь создать трубы использовать

if(pipe(gPipeFdTest) < 0) 

{ 

perror("Pipe failed"); 

exit(1); 

} 

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

Edit:

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

0

QThreads может зайти в тупик, если они заканчиваются «естественно» во время завершения.

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

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

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

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

    // Do stuff... 
} 

while(wasTerminated) 
    sleep(1); 

return; 

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

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); 
    } 
} 
Смежные вопросы