Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: Zerkin от Март 23, 2012, 11:57



Название: Завершение работы вторичного потока
Отправлено: Zerkin от Март 23, 2012, 11:57
Доброго времен суток. Вопрос следующий (может показаться тривиальным, но опыта в многопоточном программировании имею крайне мало, так что не обессудьте) :

Запускается вторичный поток, в котором происходит некоторое действие (либо анализ, либо обработка), которое в свою очередь  реализовано в отдельном классе.

Далее, для наглядности, код метода run класса вторичного потока.

Код:
void	ModeThread::run()
{
_mutex.lock();
State state = _state;
_mutex.unlock();
while (state != STOPPED)
{
_mutex.lock();
state = _state;
_mutex.unlock();
if (state == ANALYSIS)
{
UIProgressObserverObject->progress(_state, _inputFile->fileName()); //уведомление графики
Analyzer::start(_inputFile, UIResultObserverObject, _stm_type, UIProgressObserverObject);
_mutex.lock();
_state = WAITING;
_mutex.unlock();
UIProgressObserverObject->progress(_state, _inputFile->fileName());  //уведомление графики
}
else if (state == HANDLE)
{
Handler::start();
_mutex.lock();
_state = WAITING;
_mutex.unlock();
}
else if (state == WAITING)
{
_mutex.lock();
state = _state;
_waitCondition.wait(&_mutex);
_mutex.unlock();
}
}
}

Нужно прервать работу этого потока по желанию пользователя (он тыркает некоторую кнопку - поток завершается). Реализовал еще один обзервер для этих целей, всё хорошо. Но не учел тот факт что у меня состояние не изменится пока данный момент не выполниться:

Код:
Analyzer::start(_inputFile, UIResultObserverObject, _stm_type, UIProgressObserverObject);

или этот:

Код:
Handler::start();

Можно конечно, по тырканью кнопки сделать потоку терминейт, но сами понимаете, это не выход. Собственно, есть ли какой вариант, помимо вставления непосредственно кода анализа (обработки) в вышеуказанны места в коде.

Заранее спасибо.


Название: Re: Завершение работы вторичного потока
Отправлено: Igors от Март 23, 2012, 12:19
Код
C++ (Qt)
void ModeThread::run( void )
{
 while (true) {
  _mutex.lock();
  _waitCondition.wait(&_mutex);
  _mutex.unlock();
  switch (_state)
  {
    case STOPPED:
      return;
 
    case ANALYSIS:
      ...
      break;
 
    case HANDLE:
...
       break;
   }
   _state = WAITING;
  }
}
 


Название: Re: Завершение работы вторичного потока
Отправлено: Zerkin от Март 26, 2012, 10:01
Ну, я так понимаю, что в любом случае, когда я добавлю вызов функции вот в этом моменте:

Код:
 case ANALYSIS:
       ...
       break;

ничего не изменится, пока она не выполнится состояние не изменить - поток не завершить, кроме как терминейтом? Можно каких-то дополнительных комментариев, если не сложно.


Название: Re: Завершение работы вторичного потока
Отправлено: mutineer от Март 26, 2012, 10:09
в середине выполнения кода потока, без дополнительных проверок, прервать его можно только через terminate


Название: Re: Завершение работы вторичного потока
Отправлено: Zerkin от Март 26, 2012, 10:21
Но это не желательное действие, как я понимаю?


Название: Re: Завершение работы вторичного потока
Отправлено: mutineer от Март 26, 2012, 10:23
ага, нежелательное. Особенно при наличии мьютексов в коде потока


Название: Re: Завершение работы вторичного потока
Отправлено: Zerkin от Март 26, 2012, 10:54
эх, получается кроме как вставлять непосредственно код анализа в этот момент у меня вариантов нету?


Название: Re: Завершение работы вторичного потока
Отправлено: Igors от Март 26, 2012, 11:49
эх, получается кроме как вставлять непосредственно код анализа в этот момент у меня вариантов нету?
Может даже не в этот, а с "каким-то интервалом" проверять флажок отмены и выходить из run (и/или сначала из вложенных в него ф-ций). Это нормально и этот способ практически единственный (др сложны или ненадежны)


Название: Re: Завершение работы вторичного потока
Отправлено: Zerkin от Март 26, 2012, 12:10
В общем, идею понял, но мне придется многое на других уровнях изменять. Не стану использовать ни терминейт, ни что-то еще. Пока функциональность обеспечена удовлетворительная, пусть поток висит, всё равно завершится,  так что на данном этапе заниматься этим не стану, попозже или в другой версии, но в любом случае спасибо за помощь!