C++ 在单独线程中使用QTimer的规范方法
我打算创建一个工作线程,它将以1秒的间隔更新C++ 在单独线程中使用QTimer的规范方法,c++,multithreading,qt,qthread,qtimer,C++,Multithreading,Qt,Qthread,Qtimer,我打算创建一个工作线程,它将以1秒的间隔更新QTWidget(考虑到应用程序,将其视为数字时钟或进度条更新程序可能是更好的类比) 我的应用程序是特定于航空电子设备的,它计算飞行轨迹上的飞行跟踪信息,并在飞行过程中每隔1秒定期更新地图或其他QT小部件(我想你可以将其视为一种进度条,在我的情况下,进度条可以被地图或表格小部件替代)。该线程可能需要大约10-20秒来计算整个飞行数据(但是它几乎可以立即获得第一个结果)——这些结果需要每隔1秒发送到GUI,以更新飞机在地图上的位置 关于合并更新工作线程的
QTWidget
(考虑到应用程序,将其视为数字时钟或进度条更新程序可能是更好的类比)
我的应用程序是特定于航空电子设备的,它计算飞行轨迹上的飞行跟踪信息,并在飞行过程中每隔1秒定期更新地图或其他QT小部件(我想你可以将其视为一种进度条,在我的情况下,进度条可以被地图或表格小部件替代)。该线程可能需要大约10-20秒来计算整个飞行数据(但是它几乎可以立即获得第一个结果)——这些结果需要每隔1秒发送到GUI,以更新飞机在地图上的位置
关于合并更新工作线程的计时器的正确方法和错误方法,存在很多混淆。我找到的最好的知识来源是一个QtCon对话实体——似乎首选的方法是让一个workerQObject
,它不属于QThread
的子类,并且在它自己的事件处理程序中运行计时器——但是将worker线程移动到另一个我没有的线程上会有很多混淆非常理解,我正在寻找一些关于如何正确操作的规范性建议。在Lambda中这样做将是理想的,因为我可以保持逻辑和线程相对隔离,这将是理想的
我想看看是否有人能为我指出一个类似的例子的方向(特别是如果它使用现代的Lambdas)。我目前正在使用Qt5.11.2
我的工作者对象(包含QTimer
如下所示):
其实很简单:
您通常会实例化该类,开始计算,然后将其移动到专用线程。为每个计时器滴答声创建一个新线程可能是个坏主意,从性能角度看,这意味着大量的上下文切换,因此,您可以尝试以下方法:1
QThreadPool
和QRunnable
,2。或者QtConcurrent::run()
,使用QFutureWatcher
使未来真正异步,并使用信号和插槽分派结果。未来的方式是现代的方式,因为它有点像JavaScript的承诺和Dart的未来,还请注意:在线程可用之前,任务不会执行。@user9335240我只希望在模拟FlightWorker的后台运行一个发出超时信号的QTimer,沿着以下几行连接(&mTimer、&QTimer::timeout、&this、&SimulatedFlightWorker::updateFlightData)。不太确定这种语法,但我猜我必须在我的工作人员的构造函数中的某个地方这样做,只要尝试使用QtConcurrent::run([=](){/*在这里执行lambda*/})代码>这将返回一个QFuture,QFutureWatcher;连接(&watcher,信号(finished()),&myObject,插槽(handleFinished());//开始计算。QFuture future=QtConcurrent::run([=](){/*在这里执行lambda*/});watcher.setFuture(未来)
@KuberOber感谢这些规则,我遇到的一点小麻烦是如何正确初始化QObject派生类中的计时器,是否将其作为类的一个成员嵌入,以及如何正确初始化它。如果您有一个演示如何将其添加到简单GUI的小示例,那就太好了。添加QTimer
类型的成员。它必须属于该类。不需要动态分配它。例如,在类的主体中:QTimer m_updateTimer{this}代码>有没有可能你可以把一个很小的例子放在一起,展示我如何使用它-我是一个相对的QT新手,在设置正确的信号/插槽语法以使其正常工作方面仍然存在问题。在我的ex主窗口类中,我是否需要一个专用的Qthread成员来移动线程(我不想干扰GUI线程)。我想在ONXButoXXXX插槽中启动这个工作人员。你也是C++新手吗?这有很大的不同。在这一切中几乎没有Qt特异性。QThread
是一个可为空的线程句柄(当线程停止时为空),您可以像使用任何其他资源句柄一样使用它。新手的评论对回答这个问题没有帮助。尽管如此,我还是通过一个独立的例子取得了一些进展。我有一个问题,我的常规1sec emit更新没有转发到GUI线程。bool connected=connect(&mWorkerThread,&QThread::started,worker,&worker::doWork)//connected=connect(worker,&worker::progressUpdate,[=](const MMRTimedRecord&){});//this works(newline)connected=connect(worker,&worker::progressUpdate,this,&mainwindow::updateSimulatedFlight,Qt::QueuedConnection);
class SimulatedFlightWorker : public QObject
{
Q_OBJECT
public:
explicit SimulatedFlightWorker()
: mpMMRFlightData{}
{}
public slots:
// worker thread slot that computes the mpMMRFlightData
void importSimulatedFlight(
const QString& fileName,
const int aPlaybackSpeed);
void updateGUI(int secondsElapsed);
signals:
// every second during the flight we need to send a new MMR
// record to the GUI - to display on a spreadsheet or google map
void updateFlightData(const MMRTimedRecord& rMMRRecord);
// this is effectively when the worker thread is done
void flightCompleted();
private:
QTimer mTimer;
// the
std::unique_ptr<MMRFlightData> mpMMRFlightData;
};
// Experimental worker model adapted from YouTube tutorial
// by Giuseppe di Angelo https://www.youtube.com/watch?v=BgqT6SIeRn4
auto thread = new QThread;
auto worker = new SimulatedFlightWorker;
connect(thread, &QThread::started, worker, &SimulatedFlightWorker::importSimulatedFlight);
connect(worker, &SimulatedFlightWorker::flightCompleted, thread, &QThread::quit);
connect(thread, &QThread::finished, worker, &SimulatedFlightWorker::deleteLater);
worker->moveToThread(thread);
thread->start();