2016-02-09 33 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