我對Python很新,所以我很抱歉如果我的問題是業餘的。線程化UDP偵聽器函數
我想做一個簡單的程序,允許用戶看到正在廣播的UDP消息。爲了讓程序不鎖定,我當然需要創建一個單獨的線程來監聽廣播。
在我試圖執行線程之前,程序運行良好。它只是等待UDP消息,並在接收到一個消息時將它們顯示在TextView
中。當然,這鎖定了主線程。
這裏是我的代碼:(是的,我知道有我的代碼一些無關緊要的問題,但請忽略它們例如,我從來沒有關閉socket
以後我會解決這些問題。)
import socket
import select
import sys
import threading
try:
import pygtk
pygtk.require("2.0")
except:
pass
try:
import gtk
except:
print("GTK not available!")
sys.exit(1)
class GUI:
def __init__(self):
self.builder = gtk.Builder()
self.builder.add_from_file("UDPListener.ui")
dic = {"on_mainWindow_destroy" : self.quit,
"on_listenButton_clicked" : self.startThread,
"on_stopListenButton_clicked" : self.stopListening}
self.builder.connect_signals(dic)
self.listenerThread = threading.Thread(target = self.listen)
def startThread(self, widget):
self.listenerThread.start()
def listen(self):
bufferSize = 1024
IPAddress = "0.0.0.0"
IPAddress: 0.0.0.0
portNumber = 50000
udpClient = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
textView = self.builder.get_object("messagesReceivedEntry").get_buffer()
textView.text = textView.get_text(textView.get_start_iter(),textView.get_end_iter())
textView.set_text("Listening...")
try:
udpClient.bind((IPAddress, portNumber))
udpClient.setblocking(0)
except:
print "Cannot connect."
try:
while True:
result = select.select([udpClient],[],[])
message = result[0][0].recv(bufferSize)
print message
except:
print "Cannot receive message"
def quit(self, widget):
sys.exit(0)
def stopListening(self, widget):
pass
gui = GUI()
gtk.main()
代碼將運行,一切運行正常,但它從不打印任何消息(我自己廣播它們)。
UPDATE:
由於J.F.塞巴斯蒂安的回答,我改變了我的代碼,包括以下內容:
import socket
import select
import sys
import threading
import gobject
try:
import pygtk
pygtk.require("2.0")
except:
pass
try:
import gtk
except:
print("GTK not available!")
sys.exit(1)
gobject.threads_init()
class GUI:
def __init__(self, UDPClient):
self.udpClient = UDPClient
self.builder = gtk.Builder()
self.builder.add_from_file("TestUDPListenerREORG.ui")
dic = {"on_mainWindow_destroy" : self.quit,
"on_listenButton_clicked" : self.startThread,
"on_stopListenButton_clicked" : self.stopListening}
self.builder.connect_signals(dic)
self.textView = self.builder.get_object("messagesReceivedEntry").get_buffer()
self.textViewText = self.textView.get_text(self.textView.get_start_iter(),self.textView.get_end_iter())
self.listening = False
self.listenerThread = threading.Thread(target = self.listen)
def startThread(self, widget):
self.listenerThread.start()
pass
def listen(self):
try:
self.udpClient.connect()
except:
print "Cannot connect."
try:
while True:
result = select.select([self.udpClient.client],[],[])
message = result[0][0].recv(1024)
print message
gobject.idle_add(self.updateGUI, message)
except:
print "Cannot receive message"
def updateGUI(self, message):
print "updating..."
self.textView.set_text(self.textViewText + "\n" + message)
print message
def quit(self, widget):
self.udpClient.close()
sys.exit(0)
def stopListening(self, widget):
pass
class UDPClient:
def __init__(self, IPAddress, portNumber):
self.IPAddress = IPAddress
self.portNumber = portNumber
self.bufferSize = 1024
self.client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
def connect(self):
try:
self.client.bind((self.IPAddress, self.portNumber))
self.client.setblocking(0)
except: print "Cannot connect."
def close(self):
try:
self.client.close()
except:
pass
udpClient = UDPClient("0.0.0.0", 50000)
gui = GUI(udpClient)
gtk.main()
到目前爲止,一切都完美地運行。
太簡單了,謝謝。 –
@ Jordan.CarrollCS:如果您在後臺線程中運行任意GUI代碼,則僅添加'gobject.threads_init()'是不夠的。看看我提供的例子*它足夠了。請閱讀[多線程GTK應用程序 - 第1部分:誤解](否則請閱讀http://blogs.operationaldynamics.com/andrew/software/gnome-desktop/gtk-thread-awareness)。 – jfs
我實施了新的更改。你能解釋爲什麼它「不夠」,並驗證我是否正確實施了你的建議?我非常感謝你的幫助。 –