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

时间:2014-07-01 14:30:55

标签: python multithreading

我正在运行这个线程:

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

我希望在关闭Tkinter窗口时可以结束这个帖子:

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

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

不能使用thread._close()因为它已被弃用而python 3.4不允许它。

2 个答案:

答案 0 :(得分:2)

两种解决方案:

1)不要停止线程,只要在进程退出sys.exit()时就让它死掉

2)用"现在开始"开始线程。旗。 Event类专门用于向另一个线程发出信号。

以下示例启动一个连接到服务器的线程。处理任何数据,如果父信号通知线程退出,它将会。作为一项额外的安全功能,我们有一个警报信号可以杀死所有内容,只是有些事情失控。

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()

输出

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

答案 1 :(得分:0)

我在这个问题上看到的唯一真正令人满意的解决方案是不允许你的线程阻塞recv()。相反,将套接字设置为非阻塞,并将线程块放在select()中。阻塞select()内部的优点是你可以告诉select()在几个套接字中的任何一个变为准备好读取时返回,这将我们带到下一部分:作为设置线程的一部分,创建第二个套接字(本地连接的TCP套接字,例如由socketpair提供的,或者是在端口上侦听来自localhost的数据包的UDP套接字)。当你的主线程希望你的网络线程消失时,你的主线程应该向该套接字发送一个字节(或者在TCP情况下,主线程可以关闭它的套接字对的末尾)。这将导致select()返回该套接字上的ready-for-read,当您的网络线程意识到套接字已标记为ready-for-ready时,它应该立即退出。

这样做的好处是它可以在所有操作系统上运行良好,总是立即做出反应(与轮询/超时解决方案不同),在网络空闲时占用额外的零CPU周期,并且不会# 39;在多线程环境中有任何令人讨厌的副作用。缺点是它耗尽了几个额外的插座,但这通常不是什么大问题。