В конструкторе мы вызываем функцию
01 void ThreadDialog::startOrStopThreadA()
02 {
03 if (threadA.isRunning()) {
04 threadA.stop();
05 threadAButton->setText(tr("Start А"));
06 } else {
07 threadA.start();
08 threadAButton->setText(tr("Stop А"));
09 }
10 }
Когда пользователь нажимает кнопку потока А, функция
01 void ThreadDialog::startOrStopThreadB()
02 {
03 if (threadB.isRunning()) {
04 threadB.stop();
05 threadBButton->setText(tr("Start В"));
06 } else {
07 threadB.start();
08 threadBButton->setText(tr("Stop В"));
09 }
10 }
Программный код функции
01 void ThreadDialog::closeEvent(QCloseEvent *event)
02 {
03 threadA.stop();
04 threadB.stop();
05 threadA.wait();
06 threadB.wait();
07 event->accept();
08 }
Если пользователь выбирает пункт меню Quit или закрывает окно, мы даем команду останова для каждого выполняющегося потока и ожидаем их завершения (используя функцию
Если при выполнении приложения вы нажмете кнопку Start А, консоль заполнится буквами «А». Если вы нажмете кнопку Start В, консоль заполнится попеременно последовательностями букв «А» и «В». Нажмите кнопку Stop А, и тогда на экран будет выводиться только последовательность букв «В».
Синхронизация потоков
Обычным требованием для многопоточных приложений является синхронизация работы нескольких потоков. Для этого в Qt предусмотрены следующие классы:
Класс
Предположим, что нам нужно обеспечить защиту переменной
private:
QMutex mutex;
…
};
Функция
01 void Thread::run()
02 {
03 forever {
04 mutex.lock();
05 if (stopped) {
06 stopped = false;
07 mutex.unlock();
08 break;
09 }
10 mutex.unlock();
11 cerr << qPrintable(messageStr.ascii);
12 }
13 cerr << endl;
14 }
Функция
01 void Thread::stop()
02 {
03 mutex.lock();
04 stopped = true;
05 mutex.unlock();
06 }
Блокировка и разблокировка мьютекса в сложных функциях или там, где обрабатываются исключения С++, может иметь ошибки. Qt предлагает удобный класс