0

我有一个 QThread 从我的 main 产生,它正在设备上进行同步读取。读取有 1000 毫秒超时。读取被包装在一个永久循环中,并且读取受到 QMutex 的保护。基本代码是:

线程 1 - 在设备上永久读取

for (;;){
   readMutex.lock(); // Lock so that system cannot change device parameters in middle of read
   read (&devicePtr, 1000);
   readMutex.unlock; //Unlock so that thread 2 can grab lock if its waiting
}

我有另一种在主事件循环下运行的方法,可以为 devicePointer 设置一些参数。在读取设备时这样做是不安全的,因此它会尝试获取锁,然后设置参数,然后解锁互斥锁。这将允许线程 1 读取循环继续。基本代码是:

线程 2 - 设置设备参数

void setParm(){
   readMutex.lock();   //Expects to take lock as soon as Thread 1 unlocks it
   setParam (&devicePtr, PARAM);
   readMutex.unlock();   //Unlock so thread 1 can resume its read forever loop
}

当每个线程获取锁时,我在代码中有一些 qDebug 转储线程 ID。我看到的是线程 2 调用锁并阻塞,而线程 1 拥有锁并正在读取。线程 1 完成读取并解锁 Mutex。线程 1 继续循环的下一次迭代,并再次获得锁。线程 2 在readMutex.lock ()调用上保持阻塞。在线程 2 最终被允许获取锁并继续之前,这将有 5 或 6 次。

我假设 QMutex 使用循环法将线程排队,但线程 1 似乎并非如此,它能够在下一次迭代中取回锁。如果我在解锁后将QThread::msleep(250)添加到线程 1 的循环末尾,我可以强制线程 2 获取锁。睡眠可以解决问题,线程 2 能够立即获取锁并设置设备参数。

我做错了什么,这是优先事项吗?知道如何在不使用 msleep 将线程 1 置于后台的情况下通过线程进行循环吗?

4

1 回答 1

0

没有办法确保调度程序将参加一个或另一个线程。您可以尝试更改正在运行的线程的优先级,以便更好地执行一个线程,但它不会保证任何事情,并且并非所有系统都支持优先级更改(即:linux 不支持)。
您应该使用 QWaitCondition 而不是 sleep(您可以将 sleep 值作为该条件的超时传递)并使每个线程在等待该条件之前唤醒一个等待该条件的待处理线程(QWaitCondition::wakeOne)(QWaitCondition::wait )。

于 2020-07-17T03:41:37.907 回答