2009-06-22 65 views
0

我有一個在Linux平臺上用C,C++/Qt編寫的商業應用程序。該應用程序收集來自不同傳感器的數據並將其顯示在GUI上。每個用於連接傳感器的協議都是使用單例模式和Qt QThreads類的線程實現的。除一個以外的所有協議都正常工作。每個協議的線程運行函數具有以下結構:作爲單例實現的線程

void <ProtocolClassName>::run() 
{ 
while(!mStop) //check whether screen is closed or not 
{ 

mutex.lock() 
    while(!waitcondition.wait(&mutex,5)) 
    { 
    if(mStop) 
     return; 
    } 

    //Code for receiving and processing incoming data 

mutex.unlock(); 
} //end while 
} 

GUI的層次結構。

1.登錄畫面。 2.行動屏幕。

當用戶從登錄屏幕登錄時,我們進入操作屏幕,顯示所有數據並啓動不同傳感器的所有線程。它們在空閒時間等待mStop變量,當數據到達時,它們跳轉到接收和處理數據。問題協議的傳入數據是117個字節。在主GUI線程有計時器,當超時使用

<ProtocolName>::instance() function 

檢查單例類如果其真正的更新變量搶協議的運行實例,並顯示該數據。數據顯示完成後,它們將單例類中的更新變量重置爲false。有問題的協議具有1秒的更新時間,這也是協議的幀速率。當我註釋掉顯示功能時,它運行良好。但是當顯示被激活時,應用程序在6-7小時後一直掛起。我曾在很多論壇上提過這個問題,但沒有收到任何有價值的建議。我希望在這裏我會得到一些幫助。另外,我閱讀了很多有關Singleton,多線程的文獻,並發現人們總是不鼓勵使用單例,特別是在C++中。但在我的應用程序中,我可以不考慮其他設計的實現。

在此先感謝

一個不幸的程序員

+0

你需要澄清:是什麼在單獨的線程中實現?線程在哪裏生活?在GUI上?在傳感器上?在中央服務器上?誰訪問線程?這些線程是否在訪問它們的同一個應用程序上運行? – jrharshath 2009-06-22 05:19:22

+0

這是一個單一的應用程序。每個傳感器都有一個連接它的協議和一個幀速率。因此,每個協議都是以單例線程的形式實現的。當用戶通過認證並進入操作屏幕時,線程開始。每個協議線程都是主GUI THREAD類的成員。根據幀速率,我們在GUI線程中設置了一個等價的定時器,當GUI THREAD超時時抓取協議實例並根據協議類的更新變量顯示數據。在更新GUI上的數據後,將此變量重置爲false。這個更新變量是eachprotoc的成員 – rocknroll 2009-06-22 05:25:31

回答

2

我覺得單身是不是真的,你在找什麼。考慮這個:

你有(讓我們說)兩個傳感器,每個都有自己的協議(幀速率,爲我們的目的)。

現在爲每個傳感器創建「服務器」類,而不是顯式單例。這樣,您就可以隱藏你的感應器是如何工作的細節:

class SensorServer { 
protected: 
    int lastValueSensed; 
    QThread sensorProtocolThread; 
public: 
    int getSensedValue() { return lastValueSensed; } 
} 

class Sensor1Server { 
public: 
    Sensor1Server() { 
     sensorProtocolThread = new Sensor1ProtocolThread(&lastValueSensed); 
     sensorProtocolThread.start(); 
    } 
} 

class Sensor1ProtocolThread : public QThread { 
protected: 
    int* valueToUpdate; 
    const int TIMEOUT = 1000; // "framerate" of our sensor1 
public: 
    Sensor1ProtocolThread(int* vtu) { 
     this->valueToUpdate = vtu; 
    } 
    void run() { 
     int valueFromSensor; 
     // get value from the sensor into 'valueFromSensor' 
     *valueToUpdate = valueFromSensor; 
     sleep(TIMEOUT); 
    } 
} 

這樣,您就可以與具有實現單做了。

乾杯,

jrh。

+0

我必須在GUI的小部件中顯示此值,並且由於傳感器協議是GUI THREAD CLASS的成員,我必須使用協議類句柄來訪問其成員?此外,爲了通知協議線程有關傳入數據,我使用了全局中斷處理程序(在Linux上我能想到使用sigaction和sigio信號處理程序的唯一方法),它在串口接收輸入時喚醒相應的線程。在這種情況下,你能提出一些建議。 但是非常感謝你給我一個不同的觀點來思考。但我仍然不清楚這個設計如何適合我的應用程序 – rocknroll 2009-06-22 06:37:00

0

只是一個驅動器分析,但這不正確。

如果應用程序在6-7小時後「一直」掛起,您確定它不是資源(例如內存)泄漏?從其他人那裏解決有問題的協議有什麼不同嗎?你是否通過內存檢查器等來運行應用程序?

0

不知道這是你看到的原因,但你必須在你的代碼一個大胖子同步錯誤:

void <ProtocolClassName>::run() 
{ 
    while(!mStop) //check whether screen is closed or not 
    { 

     mutex.lock() 
     while(!waitcondition.wait(&mutex,5)) 
     { 
      if(mStop) 
       return; // BUG: missing mutex.unlock() 
     } 

     //Code for receiving and processing incoming data 

     mutex.unlock(); 
    } //end while 
} 

更好:

void <ProtocolClassName>::run() 
{ 
    while(!mStop) //check whether screen is closed or not 
    { 
     const QMutexLocker locker(&mutex); 
     while(!waitcondition.wait(&mutex,5)) 
     { 
      if(mStop) 
       return; // OK now 
     } 

     //Code for receiving and processing incoming data 

    } //end while 
}