Как прекратить длительный запуск Qt Thread - PullRequest
3 голосов
/ 07 февраля 2012

У меня есть потоковое приложение, в котором основной поток является потоком графического интерфейса, а вторичный поток выполняет основные вычисления внутри вложенных циклов. Теперь проблема заключается в том, как прекратить вторичный поток. Когда я нажимаю кнопку остановки в потоке GUI, он вызывает слот во вторичном потоке, который устанавливает переменную остановки в значение true. Проблема с этой техникой заключается в том, что тестирование переменной stop в циклах for (как показано ниже) недостаточно. Потому что если нажать кнопку остановки сразу после того, как поток войдет в третий цикл for, он выполнит все длинные функции, прежде чем проверит флаг остановки. Вот почему мы должны тестировать его в каждой функции перед выполнением ее содержимого, что, я думаю, не очень элегантное решение. Я не могу вызвать терминацию в этом потоке, так как этот поток выделяет некоторый приличный объем памяти, а вызов прерывания вызовет утечку этой памяти.

Так что для такого сценария, что было бы лучшим способом завершить поток и любую точку?

Следующий скелет кода просто для того, чтобы дать вам представление о том, о чем я говорю

void run( ) {

     for(int i = 0; i < 4 && !stop; i++) {
          for(int j = 0; j < 3 && !stop; j++) {
               for(int k; k < 6 && !stop; k++) {
                    callA( );
                    callB( );
                    callC( );
                    callD( );
                    callE( );
                    callF( );
                    callF( );
                    callG( );
               }
          }
     }
}

callA( ) { callL( ); }

callB( ) { callM( ); }

callC( ) { callN( ); }

callD( ) { callO( ); }

callE( ) { callP( ); }

callF( ) { callQ( ); }

callF( ) { callR( ); }

callG( ) { callS( ); }

callL( ) { sleep(20); }

callM( ) { sleep(60); }

callN( ) { QProcess( ); }

callO( ) { sleep(30);}

callP( ) { QProcess( ); }

callQ( ) { }

callR( ) { sleep(60); }

callS( ) { QProcess( ); }

Ответы [ 2 ]

1 голос
/ 07 февраля 2012

Вы можете вызвать QApplication :: processEvents () внутри вашего рабочего цикла, чтобы позволить потоку получать события.Например, событие может быть вашим основным потоком, вызывающим слот, задающий переменную, которую вы проверяете, чтобы увидеть, следует ли прерывать вашу работу.

//main thread calls this slot
void interupt_slot()
{
    stop_was_called = true;
}

void do_work()
{
   for(;;)
   {
       QApplication::processEvents();
       if(stop_was_called)
          break;

       //Work
   }

   //Exectution is over and the thread can be stopped etc
   emit its_over();

}

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

Это не будет прерывать сон потока, хотя.Если основной поток вызывает слот interupt_slot (), когда поток находится в спящем режиме, слот будет вызван, когда sleep (n) закончится.Но вы также можете подделать сон, выполняя работу в слотах, которые вызываются по таймеру.

0 голосов
/ 07 февраля 2012

Вы можете обернуть свои функции в классы и сохранить список объектов этих классов в виде списка.Поэтому вызов ваших функций будет проходить в цикле по этому списку, и у вас будет только одно кодовое место для проверки условия остановки.Кстати, чтобы избежать остановки цепей в каждом вложенном цикле, вы можете использовать goto или throw.В C ++ оставление вложенных циклов - единственный «законный» вариант использования goto.Что касается броска, B.Stroustrup предпочитает его, а не goto и рекомендует использовать его в качестве управляющей структуры.

...