繁体   English   中英

如何停止在python中运行无限循环的线程?

[英]How to stop threads running infinite loops in python?

我已经编写了一个程序,该程序具有一个主线程,通过子类化threading.Thread类可以生成许多其他线程。

每个这样的子线程运行一个无限的while循环,然后在循环内检查条件。 如果条件为true,则使用time.sleep(1)使线程休眠1秒,如果条件为false,则线程将执行一些计算。

该程序本身运行良好,并且已经实现了我想做的事情,我唯一剩下的问题是工作完成后,我似乎无法停止线程。 我希望用户能够通过按按钮或给键盘中断(如Ctrl + C)杀死所有线程。

为此,我尝试使用信号模块,并在线程的循环中插入一个条件,当主线程捕获到信号但由于某种原因而无法工作时,该条件会中断循环。 谁能帮忙吗?

编辑:这是一些相关的代码段:

def sighandler(signal,frame):
    BaseThreadClass.stop_flag = True
class BaseThreadClass(threading.Thread):
    stop_flag = False
    def __init__(self):
        threading.Thread.__init__(self)
    def run(self,*args):
        while True:
            if condition:
               time.sleep(1)
            else:
               #do computation and stuff
            if BaseThreadClass.stop_flag:
               #do cleanup
               break

您的基本方法确实有效,但是您仍然没有发布足够的代码来显示缺陷。 我添加了几行代码以使其可运行,并产生了如下结果:

$ python3 test.py
thread alive
main alive
thread alive
main alive
^CSignal caught
main alive
thread alive
main alive
main alive
main alive
^CSignal caught
^CSignal caught
main alive
^Z
[2]+  Stopped                 python3 test.py
$ kill %2

上面演示的问题涉及信号处理程序告诉所有线程退出, 主线程除外,该主线程仍在运行并仍捕获中断。 该示例代码段的完整来源为:

import threading, signal, time

def sighandler(signal,frame):
    BaseThreadClass.stop_flag = True
    print("Signal caught")

class BaseThreadClass(threading.Thread):
    stop_flag = False
    def __init__(self):
        threading.Thread.__init__(self)
    def run(self,*args):
        while True:
            if True:
               time.sleep(1)
               print("thread alive")
            else:
               #do computation and stuff
               pass
            if BaseThreadClass.stop_flag:
               #do cleanup
               break

signal.signal(signal.SIGINT, sighandler)

t = BaseThreadClass()
t.start()

while True:
    time.sleep(1)
    print("main alive")

这里的问题是主线程从不检查退出条件。 但是,因为您从未发布过主线程的功能,信号处理程序的激活方式或有关线程是否可能在不检查退出条件的情况下运行很长时间的信息……我仍然不知道您的程序出了什么问题。 库文档中显示的信号示例引发了一个异常,以转移主线程。

但是,信号是此任务的一个较低级别的概念。 我自由地编写了主线程的一个稍微天真的版本:

try:
    t = BaseThreadClass()
    t.start()
    while True:
        time.sleep(1)
        print("main alive")
except KeyboardInterrupt:
    BaseThreadClass.stop_flag = True
    t.join()

此版本捕获默认中断处理程序引发的异常,向线程发出信号以使其停止并等待它停止。 甚至可以将except子句更改为finally ,因为我们也可能希望清除其他错误的线程。

如果要进行这种“合作式”轮询关闭,则可以使用threading.Event发出信号:

import threading
import time

def proc1():
    while True:
        print("1") # payload
        time.sleep(1)

        # have we been signalled to stop?
        if not ev1.wait(0): break 

    # do any shutdown etc. here
    print ("T1 exiting")

ev1 = threading.Event()
ev1.set()

thread1 = threading.Thread(target=proc1)
thread1.start()

time.sleep(3)

# signal thread1 to stop
ev1.clear()

但是请注意,如果“有效负载”做了诸如网络或文件IO之类的阻塞操作,该操作将不会被中断。 您可以使用超时来阻止那些阻塞操作,但这显然会使您的代码复杂化。

暂无
暂无

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

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