如何在 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 和彼此使用定时器没有任何问题。
编辑:
我已经开始使用 QTimer
、QThread
和 QObject
制作 small demo。应用程序是 incomplete/buggy,但您可以看到 QTimer
是如何工作的。
我正在使用 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
和 workerQObject
- 将定时器的时间间隔设置为 20 毫秒或任何您希望它触发事件的时间间隔;时间间隔设置为 0 的定时器意味着它会尽快触发一个事件
- 将计时器连接到执行工作的工人的插槽(检查卡是否被移除等)
- 将对象的 slots/signals 连接到您的 UI 的 signals/slots(使用
QMutexLocker
将使您能够保护对两者内部数据的访问)或另一个QObject
(在工人所在的相同或不同的线程中) - 将计时器和工作程序都移动到
QThread
并启动线程
计时器将开始每 X 毫秒触发一次对您的卡的检查。 worker 然后将从计时器接收到该信号(这里不需要互斥锁,因为计时器和 worker 都具有相同的线程亲和性)。 worker 内部会发生变化,然后它会向另一个 QObject
或 UI 本身发出信号。在这一点上,互斥体开始发挥作用,除非您在您的工作线程所在的同一线程中访问 QObject
的另一个实例。
您可以添加任意数量的线程。我有一个 UI 有 6 个线程 运行 在后台访问 UI 和彼此使用定时器没有任何问题。
编辑:
我已经开始使用 QTimer
、QThread
和 QObject
制作 small demo。应用程序是 incomplete/buggy,但您可以看到 QTimer
是如何工作的。