How to implement frequent start/stop of a thread (QThread)

流过昼夜 提交于 2019-12-19 03:36:11

问题


I need to start and stop a thread very frequently using push button..I am using Qt. Recently I learned to create a QObject of the worker and move it to the object of the QThread as the correct way of implementing threads in Qt. Following is my implementation...

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();
     }
}

Initially the application works fine but after some operations of the push button to turn the working of the thread on and off the following error comes up...

QObject::killTimers(): timers cannot be stopped from another thread

I am quite puzzled at this error...do I need to implement the start/stop functions as signals and slots rather than member functions of the class?


回答1:


Don't start and stop WorkerThread. Just leave it running. Also, move your StartWork() and StopWork() methods to the public slots section. You really don't need the mutex at all.

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();
}


来源:https://stackoverflow.com/questions/14051276/how-to-implement-frequent-start-stop-of-a-thread-qthread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!