简体   繁体   English

如何实现频繁启动/停止线程(QThread)

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

I need to start and stop a thread very frequently using push button..I am using Qt. 我需要使用按钮非常频繁地启动和停止线程..我正在使用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. 最近我学会了创建一个worker的QObject并将其移动到QThread的对象,作为在Qt中实现线程的正确方法。 Following is my implementation... 以下是我的实施......

Worker.h 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.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 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.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 QObject :: killTimers():无法从另一个线程停止计时器

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? 我对这个错误感到很困惑......我是否需要将启动/停止功能实现为信号和插槽而不是类的成员函数?

Don't start and stop WorkerThread . 不要启动和停止WorkerThread Just leave it running. 让它继续运行。 Also, move your StartWork() and StopWork() methods to the public slots section. 此外,将StartWork()StopWork()方法移动到公共插槽部分。 You really don't need the mutex at all. 你根本不需要互斥锁。

Worker.h 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.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 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.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM