2012-01-04 52 views
2

我寫了一個簡單的控制檯應用程序,使用Windows套接字作爲服務器和客戶端之間的代理工作。我決定創建一個圖形界面來實時觀看所有進/出包(就像一個非常簡單的wireshark)。C++多線程窗口GUI(訪問表單)

服務器和客戶端之間的連接運行在與消息循環不同的線程上。當服務器/客戶端發送數據包時,我希望立即顯示它(例如添加到簡單的文本控件)。

但因爲我不能從其他線程訪問的形式比線程其中消息循環是我不知道如何來處理這個問題。

我已經發現了幾個解決方案: - 託管C++ - C++/CLI - C#, 但並非沒有任何使用.NET平臺。 (我真的很新的這個GUI話題,所以我甚至不能確定,你可以使用windows形式,而不.NET)

也許QT + C++可以處理這個問題,但沒有其他解決辦法比?如果不是,可以在C#/ Java中爲本機C++代碼編寫包裝器嗎?

用C/C++,其使用GUI

一定有很多的應用,什麼是做到這一點的一般方法是什麼?

+1

將次要線程的自定義消息發佈到對話框。 – ildjarn 2012-01-04 23:57:14

回答

2

你是絕對正確的,你不能訪問另一個線程中的窗口。使用:: PostMessage Win32 API命令處理此問題的正確方法(或者,如果您使用的是Win32的包裝器庫,則該包裝器中最終調用PostMessage的任何函數)。以下是來自Microsoft有關消息隊列的有用鏈接: http://msdn.microsoft.com/en-us/library/windows/desktop/ms644928(v=vs.85).aspx

+0

PostMessage +1() – 2012-01-05 00:24:06

0

一個快速而髒的Win32解決方案將涉及UI線程中的關鍵部分,文本緩衝區和計時器。

定義一些全局...

CRITICAL_SECTION bufferLock; // critical section (to be initialized somewhere) 
char dataBuffer[65536]; // contains the data that will be sent to the form 
int newdata = 0; // how much data we got (this variable must be atomic, int is ok) 
char uiDataBuffer[65536]; // data available to the form 
int overflow = 0; // just in case... 

UI線程計時器

void onTimer() 
{ 
    if (overflow) 
    { 
      // handle this 
    } 
    else 
    if (newdata) // new data to display 
    { 
      // take the lock, copy the data and release the lock quickly 
      EnterCriticalSection(&bufferLock); 
      int dataread = newdata; 
      memcpy(uiDataBuffer, dataBuffer, dataread); 
      newdata = 0; 
      LeaveCriticalSection(&bufferLock); 

      // TODO: append the text in uiDataBuffer[] to your text control 
    } 
} 

要從工作者線程調用:

void sendData (char* data, int size) 
{ 
    EnterCriticalSection (&bufferLock); 
    if(size+newdata > 65536) 
     overflow = 1; 
    else 
    { 
     memcpy(dataBuffer+newdata, data, size); 
     newdata += size; 
    } 
    LeaveCriticalSection (&bufferLock); 
} 

未測試的代碼。緩衝區大小和定時器頻率將被調整。

有可能通過使用PostMessage的()(與自定義消息)發信號通知新的數據是可用的UI,以避免輪詢與定時器的緩衝區。

如果性能是一個問題,也可以非常有效地使用無鎖FIFO隊列執行的生產者和消費者線程之間的數據交換。

單獨PostMessage()不是線程間交換數據的解決方案

+0

這兩個答案都非常有幫助,感謝他們。有沒有優雅的方式來使用自定義消息? (我的意思是如果我使用自定義消息 - 讓它成爲PACKET_ARRIVED - 它必須有一個int類型。如何確保它的值不與其他常量衝突?我應該只使用一個足夠大的數字嗎?以避免衝突? – user1131015 2012-01-05 01:59:59

+0

嘗試WM_USER +東西 – rkosegi 2012-01-05 16:21:05

+0

使用RegisterWindowMessage()獲取唯一的「自定義」消息。 – al01 2012-01-05 17:06:28

1

有一個可供選擇的一個,自由和開源,稱爲奈C++庫(http://stdex.sourceforge.net),純C++ GUI庫。 通過使用Nana庫,可以很容易地解決多線程問題。在GUI中有多線程的an article,這將是您的愛好項目的選擇。