【问题标题】:How to run different while loops without breaking any如何在不破坏任何循环的情况下运行不同的while循环
【发布时间】:2021-03-12 14:00:43
【问题描述】:

如何运行两个不同的while 循环而不破坏一个?

程序通过while 循环从 PLC(可编程逻辑控制器)收集两个不同的值。

而且这个收集应该在同时,但是当我尝试运行两个循环时,它们会中断......第一个循环只是停止返回任何值,而第二个循环是正在运行。

【问题讨论】:

  • 使用多线程......
  • 没有什么应该阻塞 gui 线程。睡眠是一个很大的禁忌,使用 QTimer 来轮询任务。繁重的处理必须在单独的线程中完成,或者您应该将其分成小块并推迟到以后。如果您想推迟任务,QTimer 可能会占用零时间。
  • 关于多线程@eyllanesc,我已经“创建”了一个QThread,所以理论上MainProgram运行到MainThread,无限循环运行在辅助QThread...
  • 关于 QTimer @doron,是的,我完全同意你的看法,但即使阅读文档我也无法理解如何使用 QTimer...
  • 请注意,您的问题目前因缺少调试细节而被关闭。如果您可以制作示例以便任何人都可以复制它们,那么您的 HowTo Question 可能会得到更好的回答。

标签: c++ windows qt loops qthread


【解决方案1】:

您的程序需要连接、读取和断开两个设备,但是,它一次只能打开一个连接。因此,连接是互斥的。您可以为此使用互斥锁。

您的代码表明,一个连接应该在一定的超时时间内无限期地轮询,而另一个连接应该通过按钮请求。我会简单地将两者放在一个插槽中,一个由按钮调用,另一个由计时器调用,并用互斥锁保护它们。

大纲:

class MainProgram : QObject {
    // Other stuff
private slots:
    void on_pushCheck_clicked();
    void readPeriodically();
    
private:
    QMutex m_mutex;
    QTimer *m_timer;
};

void MainProgram::MainProgram()
{
    // other stuff

    m_timer = new QTimer(this);
    connect(m_timer, &QTimer::timeout, this, &MainProgram::readPeriodically);
    m_timer->setInterval(2000);
    m_timer->start();
}

void MainProgram::on_pushCheck_clicked()
{
    QMutexLocker l(&m_mutex);
    
    // Read from device 1
}

void MainProgram::readPeriodically()
{
    QMutexLocker l(&m_mutex);
    
    // Read from device 2
}

这假设阅读速度非常快,因为在此期间 UI 被阻止。如果不是这种情况,您可以将读取代码放入后台工作线程。这种方法是异步的,你触发读取,一段时间后得到结果:

class DeviceReader : QObject {
public:
    void readDevice1();
    void readDevice2();
    
signals:
    void device1Data(int);
    void device2Data(int);
    
private:
    Q_INVOKABLE void doReadDevice1();
    Q_INVOKABLE void doReadDevice2();
    
private:
    QMutex m_mutex;
};

void DeviceReader::readDevice1()
{
    // Cross thread boundary
    QMetaObject::invokeMethod(this, "doReadDevice1", Qt::QueuedConnection);
}

void DeviceReader::doReadDevice1()
{
    QMutexLocker l(&m_mutex);
    
    // Read from device 1
    
    emit device1Data(1);
}

// similar for device 2


MainProgram::MainProgram() {
    DeviceReader *r = new DeviceReader;
    QThread *t = new QThread;
    
    r->moveToThread(t);

    // Connect signals for starting reads, or call them as necessary
    // Connect signal to deleteLater on thread when app closes
    // e.g. QApplication::aboutToQuit

    // The worker object does not have a "working" method.
    // It will just listen to events (signals) through the thread's exec loop
    t->start();
    
}

【讨论】:

  • 我对您的代码唯一不了解的是如何循环该过程...根据您的第一个建议@king_nak
  • 计时器将每 2 秒调用一次插槽。没有显式循环。将信号连接到线程:类似于您在原始帖子中所做的,例如connect(qApp, &QApplication::aboutToQuit, m_thread, &QObject::deleteLater);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-10
  • 2018-10-05
  • 1970-01-01
  • 1970-01-01
  • 2022-08-19
相关资源
最近更新 更多