简体   繁体   English

Python:如何停止等待 .recv() 的线程

[英]Python : how to stop a thread that's waiting for a .recv()

I have this thread running :我有这个线程运行:

def run(self):
    while 1:
        msg = self.connection.recv(1024).decode()

I wish I could end this thread when I close the Tkinter Window like this :我希望当我像这样关闭 Tkinter 窗口时可以结束这个线程:

self.window.protocol('WM_DELETE_WINDOW', self.closeThreads)

def closeThreads(self):
    self.game.destroy()
    #End the thread

Can't use thread._close() because it is deprecated and python 3.4 does not allow it.不能使用 thread._close() 因为它已被弃用并且 python 3.4 不允许它。

The only really satisfactory solution I've seen for this problem is not to allow your thread to block inside recv().对于这个问题,我见过的唯一真正令人满意的解决方案是不允许您的线程在 recv() 中阻塞。 Instead, set the socket to non-blocking and have the thread block inside select() instead.相反,将套接字设置为非阻塞并在 select() 中使用线程块。 The advantage of blocking inside select() is that you can tell select() to return when any one of several sockets becomes ready-for-read, which brings us to the next part: as part of setting up your thread, create a second socket (either a locally-connected TCP socket eg as provided by socketpair , or a UDP socket listening on a port for packets from localhost).在 select() 中阻塞的好处是,当几个套接字中的任何一个准备好读取时,您可以告诉 select() 返回,这将我们带到下一部分:作为设置线程的一部分,创建第二个套接字(本地连接的 TCP 套接字,例如由socketpair提供的,或侦听来自本地主机的数据包的端口的 UDP 套接字)。 When your main thread wants your networking thread to go away, your main thread should send a byte to that socket (or in the TCP case, the main thread could just close its end of the socket-pair).当您的主线程希望您的网络线程离开时,您的主线程应该向该套接字发送一个字节(或者在 TCP 情况下,主线程可以关闭其套接字对的末端)。 That will cause select() to return ready-for-read on that socket, and when your network thread realizes that the socket is marked ready-for-read, it should respond by exiting immediately.这将导致 select() 在该套接字上返回ready-for-read,并且当您的网络线程意识到该socket 被标记为ready-for-read 时,它应该通过立即退出来响应。

The advantages of doing it that way are that it works well on all OS's, always reacts immediately (unlike a polling/timeout solution), takes up zero extra CPU cycles when the network is idle, and doesn't have any nasty side effects in multithreaded environments.这样做的优点是它在所有操作系统上都能很好地工作,总是立即做出反应(与轮询/超时解决方案不同),在网络空闲时占用零额外的 CPU 周期,并且没有任何讨厌的副作用多线程环境。 The downside is that it uses up a couple of extra sockets, but that's usually not a big deal.缺点是它使用了几个额外的套接字,但这通常没什么大不了的。

Two solutions:两种解决方案:

1) Don't stop the thread, just allow it to die when the process exits with sys.exit() 1)不要停止线程,只要在进程退出时使用sys.exit()让它死亡

2) Start the thread with a "die now" flag. 2) 以“立即死亡”标志启动线程。 The Event class is specifically designed to signal one thread from another. Event类专门设计用于从另一个线程向一个线程发出信号。

The following example starts a thread, which connects to a server.以下示例启动一个连接到服务器的线程。 Any data is handled, and if the parent signals the thread to exit, it will.任何数据都被处理,如果父线程发出信号退出,它就会。 As an additional safety feature we have an alarm signal to kill everything, just it case something gets out of hand.作为一项额外的安全功能,我们有一个警报信号可以杀死一切,以防万一失控。

source来源

import signal, socket, threading

class MyThread(threading.Thread):
    def __init__(self, conn, event):
        super(MyThread,self).__init__()
        self.conn = conn
        self.event = event

    def handle_data(self):
        "process data if any"
        try:
            data = self.conn.recv(4096)
            if data:
                print 'data:',data,len(data)
        except socket.timeout:
            print '(timeout)'

    def run(self):
        self.conn.settimeout(1.0)
        # exit on signal from caller
        while not self.event.is_set():
            # handle any data; continue loop after 1 second
            self.handle_data()
        print 'got event; returning to caller'


sock = socket.create_connection( ('example.com', 80) )
event = threading.Event()

# connect to server and start connection handler
th = MyThread(conn=sock, event=event)

# watchdog: kill everything in 3 seconds
signal.alarm(3)

# after 2 seconds, tell data thread to exit 
threading.Timer(2.0, event.set).start()

# start data thread and wait for it
th.start()
th.join()

output输出

(timeout)
(timeout)
got event; returning to caller

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM