2015-04-20 169 views
0

我正在嘗試構建一個dll(在Clr風格中)來提供帶有盤中股票報價的Windows應用程序。該DLL由股票應用程序加載,然後其導出的函數之一將啓動下載器/生產者來獲取數據。在第二步中,一旦dll收到數據,更新者/消費者將通過SendMessage通知股票應用程序。SendMessage不起作用

我已經在很多方面測試了下載部分按預期工作(有或沒有線程支持),所以獲取數據沒有問題。在單個迭代的情況下(下面的test1),在快照引用可用之後,更新程序成功完成其任務,並且Windows UI得到更新。現在爲了不斷得到新的引號,我把下載器和更新器函數調用放在一個循環中(下面的test2)。這一次,下載程序連續工作,但更新程序中的SendMessage掛在那裏,而Windows UI未更新,直到它退出循環。

下面是測試代碼和更新代碼(讓我們拋開downloder,因爲我們知道這是工作):

// test1: single iteration, sequential, simple insert only 
// result: will update the stock app after quote download 
void test1(HWND hwnd, UINT Msg) 
{ 
    producer->DownloadStocks(); 
    prepareData(hwnd, Msg, 100); 
} 

// test2: one iteration of insert followed by updates upon quote download 
// result: will update the stock app ONLY after it is out of the while loop 
//   update in test1 is blocked, too. 
void test2(HWND hwnd, UINT Msg) 
{ 
    test1(hwnd, Msg); 
    int i = 0; 
    while (i<10) 
    { 
     producer->DownloadStocks(); 
     prepareData(hwnd, Msg, 100); 
     i++; 
    } 
} 


    void prepareData(HWND hwnd, UINT Msg, int timeout) 
    { 

     DateTime origin = DateTime(1970, 1, 1, 0, 0, 0, 0); 
     RCV_DATA rcv_data; 
     float vv = 0; 
     rcv_data.m_bDISK = FALSE; 
     rcv_data.m_nPacketNum = 1; 
     rcv_data.m_wDataType = RCV_REPORT; 
     RCV_REPORT_STRUCTEx data; 
     data.m_fBuyPrice[1] = 0; 
     data.m_fBuyVolume[1] = 0; 
     ...... 
     data.m_wMarket = (WORD)NQ_MARKET_EX; 

     while (consumer->received_data()) 
     { 
      Console::WriteLine("*********************************"); 

      while (consumer->NextRow()) 
      { 

       sprintf(data.m_szLabel, "%s", consumer->GetValue("symbol")); 
       ....... 
       data.m_fSellPrice[0] = getVal("ask"); 
       data.m_fSellVolume[0] = getVal("asksize"); 

       rcv_data.m_pReport = &data; 
       printf("\nsending update for %s", data.m_szLabel); 
       SendMessage(hwnd, Msg, (WPARAM)RCV_REPORT, (LPARAM)&rcv_data); 

      } 
     } 

    } 

我知道SendMessage函數是SYNCHR模式。它是被某些東西阻擋還是消息處理太慢?我能做些什麼來解決這個問題?我應該考慮對下載器和更新器進行線程化嗎?任何幫助,將不勝感激。

+0

你的窗口在下一個Paint事件上得到更新,如果線程空閒,它將能夠處理它。在單線程中,只有在你的循環/函數完成後,它才能獲得/處理其他事件。您需要執行多線程。 –

+0

當您使用SendMessage()時,死鎖是常見的危險。你需要使用調試器,找出擁有窗口的線程正在做什麼。總是喜歡PostMessage()。 –

+0

@Ashish Negi,我嘗試使用消費者/生產者模式的pthread。它不會工作。 – Ben

回答

0

既然你已經通過SendMessage發送數據到UI線程,你也可以發送WM_PAINT事件到該窗口。您可以使用UpdateWindowInvalidateRect來做到這一點。這會導致視圖在更新後刷新。

跨線程重繪事件與一些代碼在這裏解釋:redraw-from-another-thread

你需要保持UI線程總是免費爲用戶交互。 因此,請在後臺線程中進行阻止工作(如下載)。 std::thread可以跨平臺工作,如果可以使用c++11

+0

已經有一段時間了。最後,我解決了大多數問題。爲此,我生成一個線程,通過「SendMessage」將數據通過HWND和預定義的消息更新到UI。所以,感謝所有人的建議,特別是來自@Ashish Negi – Ben

+0

很高興它幫助.. :)堅韌不拔@Ben –

0

'while'循環和該循環中的被調用函數佔用CPU。

建議在while循環的每次迭代中自動釋放CPU。

也許通過調用nsleep()

+0

嗡嗡聲,將睡眠放置在不同的地方以達到各種長度似乎不能解除更新。 – Ben