2016-02-09 34 views
0

我使用Ubuntu 12.04和Qt 4.8.3版本。 在Qt主窗口中,我设法打开我的设备,这部分代码正在工作。 现在,当我打开设备后,如果存在卡片,我需要等待。这意味着我必须使用轮询从卡中获取数据。但是投票必须是无限循环。轮询卡的到达和删除。如何开始使用QT中的互斥锁定线程进行轮询?

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

我读了关于QThread,互斥量锁定等等,我有点困惑。 我有一个主窗口和一个工人类。在我的主窗口中,我编码为;

// 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(?????); 
......... 

首先,我必须使用connect for SIGNAL/SLOT并启动卡到达/删除轮询。如果有任何卡检测到我有信号到另一个线程从卡读取或写入卡。

所以我不知道从哪里开始或如何调用信号/插槽?我需要帮助来填补??????信号/时隙上方。

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

任何帮助,请, 亲切的问候,

+0

在附注中,'QT'用于QuickTime。 'Qt'是你正在讨论的框架。 –

+0

如果你只是轮询,你不需要*另一个线程。有一个(如果你需要非常确切的20毫秒,或者如果轮询调用实际上需要几毫秒),但你应该编写你的代码,以便它也可以单线程工作。因此,只需使用一个间隔为20 ms的重复“QTimer”,并且每个定时器信号执行轮询,将结果与先前的轮询结果进行比较,并在发生变化时发出信号。 – hyde

+0

至于如何使用Qt信号和插槽,您应该只是简单地学习基本知识:http://doc.qt.io/qt-5/signalsandslots.html进行点对点介绍,如http:/例如/doc.qt.io/qt-5/qtwidgets-mainwindows-application-example.html。 – hyde

回答

1

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

根据互斥锁的使用情况,QMutexLocker是您的朋友,我建议您使用它,而不是手动处理锁定/解锁。

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

  • 与工人QObject
  • 定时器的时间间隔设置为20ms或者你想为它跳跳虎事件的任何间隔时间一起创建QTimer;间隔设置为0的计时器意味着将尽快触发事件
  • 将计时器连接到执行工作的工作人员的插槽(检查卡是否被移除等)
  • 连接对象的插槽/信号UI的信号/插槽(使用QMutexLocker将使您,以确保双方的内部数据的访问)或其他QObject(在相同或当操作员驻留在不同的线程)
  • 移动计时器和工人都到QThread并启动线程

计时器将开始触发每X毫秒检查一次你的卡。然后,工作人员将从计时器接收该信号(因为计时器和工作人员都具有相同的线程相关性,所以不需要互斥锁)。事情会在内部发生变化,然后它会发出一个信号给另一个QObject或UI本身。在这一点上,除非你在工作人员所在的同一线程中访问QObject的另一个实例,否则互斥将起作用。

您可以添加尽可能多的线程,只要你喜欢这样做。我有一个用户界面,有6个线程在后台运行,同时访问用户界面和彼此,没有任何问题,使用计时器。

编辑: 我已经开始使用QTimerQThreadQObject一个small demo工作。申请不完整/越野车,但你可以看到QTimer是如何工作的。

+0

我编辑了我的问题。是的,我需要使用互斥锁。 – NTMS

+0

我的问题我不知道如何以及在哪里创建QTimer。我也oveToThread后如何使用连接(信号/插槽)编码。 – NTMS

+0

我明白你的建议,并找到很多例子。我的问题,我无法得到它(我的大脑卡住,因为这是我第一次)。你能告诉我一个例子,就像你在帖子上说的那样吗? – NTMS

2

使用QMutex保护的对象,在你cReader的例子:

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

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

    return result;  
} 

又见QMutexLockerQReadWriteLock

线程间通信和参数交换的常用方式是使用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将是对您有用:https://stackoverflow.com/a/35056527/4149835

附:你确定你需要使用两个不同的附加线程来检测和读/写?

+0

不正确。请阅读:'QObject及其所有子类不是线程安全的'。您仍然需要保护共享数据。进一步(再次引用你给自己的链接):'如果你正在调用一个不存在于当前线程中的QObject子类的函数,并且该对象可能接收到事件,则必须保护所有对你的QObject子类的内部数据的访问一个互斥体;否则,您可能会遇到崩溃或其他不良行为。' – rbaleksandar

+0

@rbaleksandar,作者不会在不同线程中使用相同的对象是正确的。而且,我认为他不需要使用共享数据。 –

+0

指定连接类型通常是一个坏主意。如果您需要定义连接类型,那么我已经多次阅读了99%的案例。至于读/写和检测不在同一个线程中,特别是如果检测影响其他操作,这是非常有意义的。如果将两者结合,则检测过程将被阻塞,直到读取/写入完成。 – rbaleksandar