[英]How to implement frequent start/stop of a thread (QThread)
我需要使用按鈕非常頻繁地啟動和停止線程..我正在使用Qt。 最近我學會了創建一個worker的QObject並將其移動到QThread的對象,作為在Qt中實現線程的正確方法。 以下是我的實施......
Worker.h
class worker : public QObject
{
Q_OBJECT
public:
explicit worker(QObject *parent = 0);
void StopWork();
void StartWork();
bool IsWorkRunning();
signal:
void SignalToObj_mainThreadGUI();
public slots:
void do_Work();
private:
void Sleep();
volatile bool running,stopped;
QMutex mutex;
QWaitCondition waitcondition;
};
Worker.cpp
worker::worker(QObject *parent) :
QObject(parent),stopped(false),running(false)
{
}
void worker::do_Work()
{
running = true;
while(!stopped)
{
emit SignalToObj_mainThreadGUI();
Sleep();
}
}
void worker::Sleep()
{
mutex.lock();
waitcondition.wait(&mutex,10);
mutex.unlock();
}
void worker::StopWork()
{
mutex.lock();
stopped = true;
running = false;
mutex.unlock();
}
void worker::StartWork()
{
mutex.lock();
stopped = false;
running = true;
mutex.unlock();
}
bool worker::IsWorkRunning()
{
return running;
}
MainWindow.h
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
private slots:
void on_pushButton_push_to_start_clicked();
void on_pushButton_push_to_stop_clicked();
private:
Ui::MainWindow *ui;
worker *myWorker;
QThread *WorkerThread;
};
MainWindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
myWorker = new worker;
WorkerThread = new QThread;
myWorker.moveToThread(WorkerThread);
QObject::connect(WorkerThread,SIGNAL(started()),myWorker,SLOT(do_Work()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_push_to_start_clicked()
{
if(!myWorker.IsWorkRunning())
{
myWorker->StartWork();
WorkerThread->start();
}
}
void MainWindow::on_pushButton_push_to_stop_clicked()
{
if(myWorker.IsWorkRunning())
{
myWorker->StopWork();
WorkerThread->quit();
}
}
最初應用程序工作正常,但在按鈕的某些操作后打開和關閉線程的工作,出現以下錯誤...
QObject :: killTimers():無法從另一個線程停止計時器
我對這個錯誤感到很困惑......我是否需要將啟動/停止功能實現為信號和插槽而不是類的成員函數?
不要啟動和停止WorkerThread
。 讓它繼續運行。 此外,將StartWork()
和StopWork()
方法移動到公共插槽部分。 你根本不需要互斥鎖。
Worker.h
class worker : public QObject
{
Q_OBJECT
public:
explicit worker(QObject *parent = 0);
signal:
void SignalToObj_mainThreadGUI();
void running();
void stopped();
public slots:
void StopWork();
void StartWork();
private slots:
void do_Work();
private:
volatile bool running,stopped;
};
Worker.cpp
worker::worker(QObject *parent) :
QObject(parent), stopped(false), running(false)
{}
void worker::do_Work()
{
emit SignalToObj_mainThreadGUI();
if ( !running || stopped ) return;
// do important work here
// allow the thread's event loop to process other events before doing more "work"
// for instance, your start/stop signals from the MainWindow
QMetaObject::invokeMethod( this, "do_Work", Qt::QueuedConnection );
}
void worker::StopWork()
{
stopped = true;
running = false;
emit stopped();
}
void worker::StartWork()
{
stopped = false;
running = true;
emit running();
do_Work();
}
MainWindow.h
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
signals:
void startWork();
void stopWork();
private slots:
void on_pushButton_push_to_start_clicked();
void on_pushButton_push_to_stop_clicked();
private:
Ui::MainWindow *ui;
worker *myWorker;
QThread *WorkerThread;
};
MainWindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
myWorker = new worker;
WorkerThread = new QThread;
myWorker.moveToThread(WorkerThread);
connect( this, SIGNAL(startWork()), myWorker, SLOT(StartWork()) );
connect( this, SIGNAL(stopWork()), myWorker, SLOT(StopWork()) );
}
void MainWindow::on_pushButton_push_to_start_clicked()
{
emit startWork();
}
void MainWindow::on_pushButton_push_to_stop_clicked()
{
emit stopWork();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.