如何在 QT 中使用互斥锁定线程开始轮询?

How do I start polling with mutex locked thread in QT?

我正在使用 Ubuntu 12.04 和 Qt 版本 4.8.3。 在 Qt main window 中,我设法打开了我的设备,这部分代码正在运行。 现在,在我打开设备后,如果有卡,我需要等待。这意味着我必须使用轮询从卡中获取数据。但是轮询必须是无限循环的。轮询卡的到达和移除。

每 20 毫秒轮询卡片到达的示例,当检测到卡片时,我需要每 20 毫秒切换轮询以移除卡片。因此,当检测到卡片到达或移除时,我的应用程序会发出 Qt 事件信号,这样另一个 Qt 线程现在可以继续 read/write 卡片。

我读到有关 QThread、互斥锁等的信息,但我有点困惑。 我有一个 main window 加上一个 worker class。在我的 mainwindow 中,我编码为;

// Open a reader (from my SDK)
cReader.open 

//If the reader is open use;

thread = new QThread();
worker = new Worker();
worker->moveToThread(thread);
connect(worker,SIGNAL(??????),SLOT(?????);
connect(worker,SIGNAL(?????),SLOT(?????);
.........

首先,我必须使用连接 SIGNAL/SLOT 并启动网卡 arrival/removal 轮询。如果检测到任何卡,我会向另一个线程发送信号以从卡中读取或写入卡。

所以我不知道从哪里开始或如何调用signal/slot?我需要帮助来填写 ??????以上 SIGNAL/SLOT.

编辑:我还需要轮询线程和卡片处理线程共享的互斥锁。这是因为如果打开卡轮询命令将使我的 mifare 会话无效。

请帮忙, 亲切的问候,

使用QMutex保护对象,以您的cReader为例:

// class member
QMutex m_mutex;
//...

QByteArray MyClass::safeReadSomeData()
{
    m_mutex.lock();
    QByteArray result = cReader.read();
    m_mutex.unlock();

    return result;    
}

另见 QMutexLocker, QReadWriteLock

线程间通信和参数交换的常用方式是使用signals & slots。示例:

thread = new QThread();
worker = new Worker();
worker->moveToThread(thread);
connect( thread, SIGNAL(started()), worker, SLOT(startMyWork()) );
connect( worker, SIGNAL(sigCardDetected()), someOtherObject, SLOT(onCardDetected()) );
thread->start();
//...

来自官方文档的有用文章:Threads and QObjects

此外,我认为关于 QThread 的回答对您有用:

p.s。您确定需要使用两个不同的附加线程来检测和 reading/writing?

它不是线程安全的(除非一个 QObject 访问另一个 QObject 中的数据并且两者属于同一个线程)。

就互斥量的使用而言,QMutexLocker 是您的朋友,我建议您使用它而不是手动处理 locking/unlocking。

如果您重新阅读您的问题,您会发现您大量使用间隔。我们如何处理间隔?使用 QTimer。这是我的建议:

  • 创建一个 QTimer 和 worker QObject
  • 将定时器的时间间隔设置为 20 毫秒或任何您希望它触发事件的时间间隔;时间间隔设置为 0 的定时器意味着它会尽快触发一个事件
  • 将计时器连接到执行工作的工人的插槽(检查卡是否被移除等)
  • 将对象的 slots/signals 连接到您的 UI 的 signals/slots(使用 QMutexLocker 将使您能够保护对两者内部数据的访问)或另一个QObject(在工人所在的相同或不同的线程中)
  • 将计时器和工作程序都移动到 QThread 并启动线程

计时器将开始每 X 毫秒触发一次对您的卡的检查。 worker 然后将从计时器接收到该信号(这里不需要互斥锁,因为计时器和 worker 都具有相同的线程亲和性)。 worker 内部会发生变化,然后它会向另一个 QObject 或 UI 本身发出信号。在这一点上,互斥体开始发挥作用,除非您在您的工作线程所在的同一线程中访问 QObject 的另一个实例。

您可以添加任意数量的线程。我有一个 UI 有 6 个线程 运行 在后台访问 UI 和彼此使用定时器没有任何问题。

编辑: 我已经开始使用 QTimerQThreadQObject 制作 small demo。应用程序是 incomplete/buggy,但您可以看到 QTimer 是如何工作的。