【问题标题】:Closing all threads with a keyboard interrupt用键盘中断关闭所有线程
【发布时间】:2012-07-11 07:09:28
【问题描述】:

我在这里尝试做的是使用键盘中断来退出程序中所有正在进行的线程。这是创建线程的代码的精简版本:

for i in taskDictionary:
    try:
        sleep(60)
        thread = Thread(target = mainModule.executeThread)
        thread.start()
    except KeyboardInterrupt:
        thread.__stop()

程序本身要复杂得多,考虑到影响线程的大量不同变量,甚至可以选择以顺序模式启动,其中任务不是线程化的,而是一个接一个地启动,因此可能我刚刚想出的这个小变化有一些问题。 我以产生 50/50 结果的方式做到了这一点。中断会起作用,但线程永远不会干净地退出。有时它们会继续运行,但会停止未来线程的执行,有时它们会因中断而出现大量错误而退出,有时中断什么也不做。上次我运行这个程序时,程序停止了任何未来线程的执行,但没有停止当前线程。 有什么方法可以退出线程而不进入线程实际执行的模块?

【问题讨论】:

    标签: python multithreading


    【解决方案1】:

    一个类似的问题是“你如何杀死一个线程?”

    您在线程中创建一个退出处理程序,该处理程序由线程模块中的锁或事件对象控制。然后,您只需移除锁或向事件对象发出信号。这会通知线程它应该停止处理并正常退出。在主程序中向线程发出信号后,剩下要做的就是使用main 中的thread.join() 方法,该方法将等待线程关闭。

    一个简短的例子:

    import threading
    import time
    
    def timed_output(name, delay, run_event):
        while run_event.is_set():
            time.sleep(delay)
            print name,": New Message!"
    
    
    def main():
        run_event = threading.Event()
        run_event.set()
        d1 = 1
        t1 = threading.Thread(target = timed_output, args = ("bob",d1,run_event))
    
        d2 = 2
        t2 = threading.Thread(target = timed_output, args = ("paul",d2,run_event))
    
        t1.start()
        time.sleep(.5)
        t2.start()
    
        try:
            while 1:
                time.sleep(.1)
        except KeyboardInterrupt:
            print "attempting to close threads. Max wait =",max(d1,d2)
            run_event.clear()
            t1.join()
            t2.join()
            print "threads successfully closed"
    
    if __name__ == '__main__':
        main()
    

    如果您真的需要杀死线程的功能,请使用多处理。它允许您将 SIGTERM 发送到各个“进程”(它也非常类似于线程模块)。一般来说,线程适用于您受 IO 限制的情况,而多处理适用于您真正受处理器限制的情况。

    【讨论】:

    • 有了线程的配合,你可以随心所欲地杀死它。没有线程的配合,就没有安全的方法,条条大路通通痛。
    • 绝妙的答案!不完全是我想要的,但足够广泛,我能够将逻辑调整为我需要的!谢谢!
    • 我正在使用线程,因为我不想要无限的 while True 循环。这浪费了你所有的 CPU 时间......几乎是字面意思。我已经做了这样的事情,并且没有睡眠它一次将 CPU% 提高到 100% 并且有一个小的睡眠,这只会有一点帮助。有没有办法做到这一点没有一段时间真?
    • @Dylan 无限循环只是为了提供一个简洁的工作示例。通常一个人会在主循环中完成一些主要任务。尽管如此,即使time.sleep(.001) 也应该显着降低 CPU 负载。在time.sleep(.010),我的python 线程以不到1% 的CPU 运行。线程应该用于 IO 绑定的进程,或者需要定期检查的资源。主循环应该执行你的主要代码,如果它需要资源,可能会休眠 50 毫秒以等待。如果处理确实对时间敏感,您始终可以使用lock 协议来休眠和唤醒。
    • 如果线程在等待 I/O 时被阻塞怎么办。事件是否以某种方式唤醒它。
    【解决方案2】:

    有几个选项不需要在线程之间使用锁或其他信号。一种是将线程设置为daemons,当主线程退出时会自动关闭。另一种是使用processes,它有一个可以从主进程调用的终止方法,如果你需要杀死它们并保持主程序运行。

    如果您有线程阻塞输入,这两种方法都特别有用。虽然在大多数情况下使用超时和定期检查信号不会产生太多开销,但使用守护进程或进程无需任何繁忙的循环或显着增加的复杂性。

    查看this question的答案,了解更多关于这些解决方案的详细信息以及关于杀死线程问题的讨论。

    【讨论】:

      猜你喜欢
      • 2014-08-11
      • 2012-04-24
      • 2018-05-30
      • 1970-01-01
      • 2017-11-08
      • 2012-05-29
      • 2014-10-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多