Qthread — проблемы с закрытием потоков

В течение последних нескольких дней я пробовал новый предпочтительный подход к использованию QThreads без создания подклассов QThread. Проблема, с которой я сталкиваюсь, заключается в том, что я пытаюсь закрыть набор потоков, которые я создал. Я регулярно получаю сообщение «Уничтожен, пока поток все еще работает» (если я работаю в режиме отладки, я также получаю диалоговое окно «Ошибка сегментации»). Мой код очень прост, и я пытался следовать примерам, которые мне удалось найти в Интернете.

Моя базовая установка выглядит следующим образом: у меня есть простой класс, который я хочу запустить в отдельном потоке; на самом деле я хочу запустить 5 экземпляров этого класса, каждый в отдельном потоке. У меня есть простой диалог с кнопкой для запуска каждого потока и кнопкой для остановки каждого потока (10 кнопок). Когда я нажимаю одну из кнопок «Пуск», создается новый экземпляр тестового класса, создается новый QThread, вызывается movetothread, чтобы получить объект тестового класса в поток... также, поскольку у меня есть пара других членов тестового класса, которым нужно переместиться в поток, я вызываю movetothread еще несколько раз с этими другими элементами. Обратите внимание, что одним из этих элементов является QUdpSocket, и хотя это может не иметь смысла, я хотел убедиться, что сокеты могут быть перемещены в отдельный поток таким образом... Я не проверял использование сокета в нить в этот момент.

Запуск потоков, похоже, работает нормально. Когда я использую команду linux top, чтобы увидеть, созданы ли и запущены ли потоки, они отображаются, как и ожидалось.

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

Класс, который должен работать в отдельном потоке:

// Declaration
class TestClass : public QObject
{
Q_OBJECT
public:
explicit TestClass(QObject *parent = 0);
QTimer m_workTimer;
QUdpSocket m_socket;

Q_SIGNALS:
void finished();

public Q_SLOTS:
void start();
void stop();
void doWork();

};

// Implementation
TestClass::TestClass(QObject *parent) :
QObject(parent)
{

}

void TestClass::start()
{
  connect(&m_workTimer, SIGNAL(timeout()),this,SLOT(doWork()));
  m_workTimer.start(50);
}

void TestClass::stop()
{
  m_workTimer.stop();
  emit finished();
}

void TestClass::doWork()
{
int j;
for(int i = 0; i<10000; i++)
  {
    j = i;
  }
}

Внутри моего основного приложения код, вызываемый для запуска первого потока (аналогичный код существует для каждого из других потоков):

mp_thread1 = new QThread();
mp_testClass1 = new TestClass();
mp_testClass1->moveToThread(mp_thread1);
mp_testClass1->m_socket.moveToThread(mp_thread1);
mp_testClass1->m_workTimer.moveToThread(mp_thread1);

connect(mp_thread1, SIGNAL(started()), mp_testClass1, SLOT(start()));
connect(mp_testClass1, SIGNAL(finished()), mp_thread1, SLOT(quit()));
connect(mp_testClass1, SIGNAL(finished()), mp_testClass1, SLOT(deleteLater()));
connect(mp_testClass1, SIGNAL(finished()), mp_thread1, SLOT(deleteLater()));
connect(this,SIGNAL(stop1()),mp_testClass1,SLOT(stop()));

mp_thread1->start();

Также внутри моего основного приложения этот код вызывается при нажатии кнопки остановки для определенного потока (в данном случае потока 1):

emit stop1();

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

Мы будем очень признательны за любые рекомендации.

Спасибо,

Брайан


person Bryan Greenway    schedule 28.06.2012    source источник


Ответы (1)


http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

«Наконец, чтобы предотвратить неприятные сбои из-за того, что поток еще не был полностью закрыт, когда он был удален, мы подключаем метод finish() потока (не рабочий!) к его собственному слоту deleteLater(). Это приведет к тому, что поток быть удалены только после его полного закрытия».

Пожалуйста, попробуйте заменить:

    connect(mp_testClass1, SIGNAL(finished()), mp_thread1, SLOT(deleteLater()));

с участием:

    connect(mp_thread1, SIGNAL(finished()), mp_thread1, SLOT(deleteLater()));
person Nemo    schedule 16.10.2012