Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 如何实现线程的频繁启动/停止(QThread)_Multithreading_Qt_Qthread - Fatal编程技术网

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

Multithreading 如何实现线程的频繁启动/停止(QThread),multithreading,qt,qthread,Multithreading,Qt,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 I

我需要启动和停止线程非常频繁地使用按钮..我使用的是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;
};
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;
};
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;
};
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;
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::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();
     }
}
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::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();
}
main window.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;
};
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;
};
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;
};
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;
main window.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::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();
     }
}
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::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();
}
最初,应用程序工作正常,但在按下按钮打开和关闭线程工作后,出现以下错误

QObject::killTimers():无法从其他线程停止计时器


我对这个错误感到非常困惑…我是否需要将启动/停止函数实现为信号和插槽,而不是类的成员函数?

不要启动和停止
WorkerThread
。让它继续运行。另外,将您的
StartWork()
StopWork()
方法移动到公共插槽部分。你根本不需要互斥

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;
};
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;
};
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;
};
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;
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::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();
     }
}
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::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();
}
main window.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;
};
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;
};
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;
};
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;
})

main window.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::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();
     }
}
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::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();
}

尽量不要在线程上调用start()和quit()。一旦将worker对象移动到线程,就应该直接控制worker。start()和quit()仅用于启动和关闭线程。关于invokeMethod:当我使用你的代码时,它不起作用,根据我的说法,你应该使用字符串“do_work”而不是SLOT(do_work())。这对我来说很有效。@sluki:关于
invokeMethod
参数,你是对的。我更新了我的答案以使用正确的格式。非常好的答案,谢谢!接下来,假设你有一个do_Work函数,它是while(循环),我怎么能中断这个动作呢?我注意到QueuedConnection在处理循环时不会停止循环,所以我想我必须亲自检查它?@Dariusz:在这种情况下,你不需要
while
循环
do_Work
被连续(异步)调用,直到切换到
running
stopped
的状态。因此,只需将
while
循环的主体放入
do_Work
方法,并在需要时使用一个标志(如答案所示)来打破“循环”。