Qt Thread在运行时立即失败,这是我的标题:
class Stepper1_run : public QThread
{
public:
void system_run();
private:
void run();
};
这是.cpp代码:
void Stepper1_run::run(){
//do whatever
}
void Stepper1_run::system_run()
{
Stepper1_run stepper1_run;
stepper1_run.start();
}
当从gui点击按钮时调用它:
void MainWindow::on_button_run_clicked()
{
Stepper1_run stepper1_run;
stepper1_run.system_run();
}
最初,system_run()
函数本身就是一个函数,我被告知它需要成为该类的成员,否则该线程将立即关闭。不幸的是,该函数仍然在运行时立即关闭并出现错误:`QThread:在线程仍在运行时被销毁"程序退出。
是什么导致这种情况发生?
答案 0 :(得分:2)
您已在堆栈中声明了您的线程对象,此处:
void MainWindow::on_button_run_clicked()
{
Stepper1_run stepper1_run; // <- Stepper1_run is instantiated
stepper1_run.system_run(); // <- Thread starts
} // <- stepper1_run goes out of scope and is destroyed.
一旦超出范围,对象就会被销毁,这会在您调用system_run()
后立即发生,因此会出错。
使其成为集体成员是一种选择。你可以把它变成一个指针(或者一个Qt自动指针);如果您一次只能运行此线程的一个实例,这是合适的。要启动线程,请实例化Stepper1_run
,启动它并存储指针。要停止线程,请指示它停止,加入它,然后删除实例并重置指针。在销毁包含类时,请务必在销毁之前停止线程(您可以执行常规停止 - &gt; join - &gt;删除包含类析构函数中的逻辑)。
更新;评论中要求的示例:
class MainWindow : ... {
...
public:
~MainWindow ();
public slots:
void startSystem ();
void stopSystem ();
private:
QScopedPointer<Stepper1_run> stepper_;
};
MainWindow::~MainWindow () {
stopSystem(); // <- proper termination of thread on exit
}
void MainWindow::startSystem () {
stopSystem();
stepper_.reset(new Stepper1_run());
stepper_->system_run();
}
void MainWindow::stopSystem () {
if (stepper_) {
stepper_->whateverStopsTheThread(); // <- you'd need to implement this
stepper_->wait(); // <- i.e. join; waits for thread to terminate
stepper_.reset(); // <- i.e. delete
}
}
该示例是众多可能性中的一种,您的场景可能会有所不同。为简洁起见,也省略了错误处理/异常安全(具体细节也取决于您的情况)。上面的例子假设只是一个线程应该运行,并且启动一个新线程应该终止旧线程。
顺便说一句,请注意,使用slots,您只需connect()
按钮的clicked()
信号即可startSystem()
。这也为您提供了从其他线程调用startSystem()
和stopSystem()
的方法,让Qt处理同步细节。
如果您打算将指针传递给其他对象(它与QSharedPointer
的API略有不同,请使用QScopedPointer
,请阅读文档)。如果你想出于某种原因使用C风格的指针,它类似于上述情况中的QScopedPointer
,只需记住在NULL
构造函数中将其初始化为MainWindow
做。
答案 1 :(得分:-2)
只需在标题上声明stepper1_run就像这样。
class Stepper1_run : public QThread
{
public:
void system_run();
private:
void run();
Stepper1_run stepper1_run;
};
void MainWindow::on_button_run_clicked()
{
stepper1_run.system_run();
}