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
C++ 在单独线程中使用QTimer的规范方法_C++_Multithreading_Qt_Qthread_Qtimer - Fatal编程技术网

C++ 在单独线程中使用QTimer的规范方法

C++ 在单独线程中使用QTimer的规范方法,c++,multithreading,qt,qthread,qtimer,C++,Multithreading,Qt,Qthread,Qtimer,我打算创建一个工作线程,它将以1秒的间隔更新QTWidget(考虑到应用程序,将其视为数字时钟或进度条更新程序可能是更好的类比) 我的应用程序是特定于航空电子设备的,它计算飞行轨迹上的飞行跟踪信息,并在飞行过程中每隔1秒定期更新地图或其他QT小部件(我想你可以将其视为一种进度条,在我的情况下,进度条可以被地图或表格小部件替代)。该线程可能需要大约10-20秒来计算整个飞行数据(但是它几乎可以立即获得第一个结果)——这些结果需要每隔1秒发送到GUI,以更新飞机在地图上的位置 关于合并更新工作线程的

我打算创建一个工作线程,它将以1秒的间隔更新
QTWidget
(考虑到应用程序,将其视为数字时钟或进度条更新程序可能是更好的类比)

我的应用程序是特定于航空电子设备的,它计算飞行轨迹上的飞行跟踪信息,并在飞行过程中每隔1秒定期更新地图或其他QT小部件(我想你可以将其视为一种进度条,在我的情况下,进度条可以被地图或表格小部件替代)。该线程可能需要大约10-20秒来计算整个飞行数据(但是它几乎可以立即获得第一个结果)——这些结果需要每隔1秒发送到GUI,以更新飞机在地图上的位置

关于合并更新工作线程的计时器的正确方法和错误方法,存在很多混淆。我找到的最好的知识来源是一个QtCon对话实体——似乎首选的方法是让一个worker
QObject
,它不属于
QThread
的子类,并且在它自己的事件处理程序中运行计时器——但是将worker线程移动到另一个我没有的线程上会有很多混淆非常理解,我正在寻找一些关于如何正确操作的规范性建议。在Lambda中这样做将是理想的,因为我可以保持逻辑和线程相对隔离,这将是理想的

我想看看是否有人能为我指出一个类似的例子的方向(特别是如果它使用现代的Lambdas)。我目前正在使用Qt5.11.2

我的工作者对象(包含
QTimer
如下所示):

其实很简单:

  • 您的计算是在QObject派生类中完成的

  • 更新是通过该对象中的信号发出的

  • 计算是以10-20毫秒的时间进行的

  • 计算是从零持续时间计时器触发的–它不是计时器,而是检测线程中事件循环空闲状态的一种方法

  • 更新由1秒计时器触发

  • 这个类可以在任何线程上运行——它甚至可以在GUI线程上运行,但会使它的响应性降低一点(但不是完全没有响应)


    您通常会实例化该类,开始计算,然后将其移动到专用线程。

    为每个计时器滴答声创建一个新线程可能是个坏主意,从性能角度看,这意味着大量的上下文切换,因此,您可以尝试以下方法: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();