2012-12-17 22 views
1

我猜測我需要做線程,但在我教自己一些不好的做法之前,我想確保我正在以這種正確的方式進行。我該如何解決凍結點擊後處理信息的GTK按鈕?

基本上我有一個「聊天」應用程序,可以告訴偵聽或ping通收件人的IP地址:端口(在我目前的情況下只是127.0.0.1:1300)。當我打開我的應用程序兩次(第一個聽,第二個發送ping)時,我選擇一個並告訴它聽(哪個是While語句,只是不斷收聽,直到它收到ping消息),另一個會ping它。它的作品只是桃色!

問題是,當我單擊「偵聽ping」按鈕時,它將進入粘貼的「向下」模式並凍結「視覺」,但它將UDP數據包消息打印到控制檯,因此我知道它並非實際凍結。所以我的問題是我如何做到這一點,所以我可以點擊「收聽」按鈕並讓它「聽」,同時有一個「工作」取消按鈕,以便用戶可以取消該過程,如果它需要太長時間?

+0

讓我們只是說我有一個按鈕,當我點擊那個按鈕時,它有一個永遠while()循環在回調/信號...我怎麼做,所以按鈕不凍結了?它的錯誤導致用戶 – Xenland

回答

2

這很可能是因爲您使用同步(阻塞)套接字IO而發生的。您的服務器應用程序很可能會阻塞recv()/read(),這會阻止您的線程執行,直到某些數據到達;它然後處理數據並返回到阻塞狀態。因此,按鈕由GTK呈現爲按下。

對於這個問題,基本上有兩種通用方法。第一個是線程。但我會在更簡單的應用程序中推薦它。這種方法通常很容易出錯,而且實施起來相當複雜。

第二種方法是異步IO。首先,您可以使用select()/poll()函數等待多個FD中的一個發送信號(在'接收數據','發送數據','連接接受'等事件上)。但是在主循環不可用的GUI應用程序中(我不確定GTK,但許多GUI工具包都是這種情況),通常這是不可能的。在這種情況下,您可以使用通用異步IO庫(如boost asio)。使用GLIB,IIRC,您可以創建套接字交互的通道(g_io_channel_unix_new()),然後爲它們分配回調(g_io_add_watch()),在發生某些有趣的事情時將調用這些回調。異步IO背後的想法很簡單:你要求操作系統做一些事情(發送數據,等待事件),然後你做其他重要的事情(GUI交互等),直到你要求的東西完成(你必須能夠接收這些事件的通知)。

所以,這裏是你接下來可能要學什麼:

  • select()/poll()(後者通常更易於使用)
  • 升壓ASIO庫
  • GLIB渠道和異步IO
+0

Awsome你讓我想出了方框,有一些擺弄我做了一些在GTK之前創建的線程,並在進入適當的隊列時管理工作。例如,我創建了兩個pthreads,一個用於不斷接收UDP數據包,並將它們發送到相應的處理器函數,另一個線程用於查找隊列中標記爲要發送的數據。 – Xenland

+1

不錯!但即使線程看起來更容易實現(而且看起來更明顯),我強烈建議尋求我提到的異步IO方法:) –