簡體   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