【发布时间】:2012-12-29 02:14:58
【问题描述】:
我正在使用 Qt5,我通过 moveToThread() 将 QObject 工作线程传递给 QThread 的实例来实现线程。我的实现看起来像这样..
Worker.h
class worker : public QObject
{
Q_OBJECT
public:
explicit worker(QObject *parent = 0);
bool IsWorkRunning();
void MoveObjectToThread();
signal:
void SignalToObj_mainThreadGUI();
public slots:
void do_Work();
void StopWork();
void StartWork();
private:
void Sleep();
QThread *workerthread;
volatile bool running,stopped;
};
Worker.cpp
worker::worker(QObject *parent) :
QObject(parent),stopped(false),running(false)
{
}
void worker::do_Work()
{
running = true;
while(!stopped)
{
if(running)
{
emit SignalToObj_mainThreadGUI();
workerthread->msleep(20);
}
}
}
void worker::StopWork()
{
running = false;
}
void worker::StartWork()
{
running = true;
}
bool worker::IsWorkRunning()
{
return running;
}
void MoveObjectToThread()
{
workerthread = new QThread;
QObject::connect(workerthread,SIGNAL(started()),this,SLOT(do_Work()));
this->moveToThread(workerthread);
workerthread->start();
}
MainWindow.h
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
signals:
void Startwork_mainwindow();
void Stopwork_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;
bool work_started;
};
MainWindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),work_started(false),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QObject::connect(this,SIGNAL(Startwork_mainwindow()),&myWorker,SLOT(StartWork()));
QObject::connect(this,SIGNAL(Stopwork_mainwindow()),&myWorker,SLOT(StopWork()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_push_to_start_clicked()
{
if(!work_started)
{
myWorker.MoveObjectToThread();
work_started = true;
}
if(!myWorker.IsWorkRunning())
emit this->Startwork_mainwindow();
}
void MainWindow::on_pushButton_push_to_stop_clicked()
{
if(myWorker.IsWorkRunning())
emit this->Stopwork_mainwindow();
}
不知道为什么以下两个信号/插槽对似乎不起作用
QObject::connect(this,SIGNAL(Startwork_mainwindow()),&myWorker,SLOT(StartWork()));
QObject::connect(this,SIGNAL(Stopwork_mainwindow()),&myWorker,SLOT(StopWork()));
因此,一旦 QThread 对象的started() 信号触发了do_Work() 插槽,我就无法启动或停止线程。仅供参考,我的这篇文章是我之前的帖子here described 的延续。任何见解都会有所帮助...谢谢
【问题讨论】:
-
在进行任何信号连接之前,您是否尝试过移至线程。就像你做完之后一样?当你的线程不运行时,你的外部 while 循环不是在疯狂地旋转吗?也许它也需要睡眠来帮助调度程序。
-
我不会使用
moveToThread,而是重新实现QThread。它更容易理解,而且我认为更不容易出错。并且在主线程使用QObject::connect到另一个线程时,不要使用AutoConnect连接到另一个线程,而是使用QueuedConnection。 -
如果我使用 Qt::Directconnection 会怎样?在论坛中我读到的一些地方将 QThread 子类化不是一个好习惯……由于这种使用范式,Qt5 已经公开了许多静态私有函数
-
您不想重新实现
QThread。查看这个和链接的讨论,了解原因。 stackoverflow.com/questions/4093159/… -
您是否尝试过在不启动私有 QThread 实例的情况下在您尝试移动到线程的对象内执行此操作?基本上我的意思是你应该首先尝试在你的对象之外(在主窗口甚至 main.cpp 中)创建 QThread 并将你的对象实例移动到线程并在那里启动它。
标签: multithreading qt signals-slots qthread qt5