Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
无法使用键盘Ctrl+;中断线程化Python控制台应用程序;Windows上的C_Python_Windows_Exception_Signals - Fatal编程技术网

无法使用键盘Ctrl+;中断线程化Python控制台应用程序;Windows上的C

无法使用键盘Ctrl+;中断线程化Python控制台应用程序;Windows上的C,python,windows,exception,signals,Python,Windows,Exception,Signals,我无法在Windows上使用Ctrl+C中断我的线程Python生产应用程序,它继续运行,尝试了异常和信号处理。这里是非常简化的代码版本,不会中断。单线程应用程序终止良好,与多线程Linux版本相同。谁能帮我解决这个麻烦?提前谢谢 import threading import time class FooThread(threading.Thread): stop_flag = False def __init__(self): threading.Thre

我无法在Windows上使用Ctrl+C中断我的线程Python生产应用程序,它继续运行,尝试了异常和信号处理。这里是非常简化的代码版本,不会中断。单线程应用程序终止良好,与多线程Linux版本相同。谁能帮我解决这个麻烦?提前谢谢

import threading
import time

class FooThread(threading.Thread):
    stop_flag = False

    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        while not self.stop_flag:
            print(1)
            time.sleep(1)

t = FooThread()
t.start()

try:
    t.join()
except KeyboardInterrupt:
    t.stop_flag = True
    t.join()

您将线程设置为守护进程,但还需要保持“主”线程处于活动状态,以侦听信号或键盘中断

带有信号的简单工作实现:

import threading
import time
import sys
import signal

class FooThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        while not self.stop_flag:
            print(1)
            time.sleep(1)

    stop_flag = False

def main():
    t = FooThread()
    def signal_handler(signal, frame):
        print('You pressed Ctrl+C!')
        t.stop_flag = True
        t.join()

    signal.signal(signal.SIGINT, signal_handler)
    t.start()

    while not t.stop_flag:
        time.sleep(1)

if __name__ == "__main__":
    main()

您将线程设置为守护进程,但还需要保持“主”线程处于活动状态,以侦听信号或键盘中断

带有信号的简单工作实现:

import threading
import time
import sys
import signal

class FooThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        while not self.stop_flag:
            print(1)
            time.sleep(1)

    stop_flag = False

def main():
    t = FooThread()
    def signal_handler(signal, frame):
        print('You pressed Ctrl+C!')
        t.stop_flag = True
        t.join()

    signal.signal(signal.SIGINT, signal_handler)
    t.start()

    while not t.stop_flag:
        time.sleep(1)

if __name__ == "__main__":
    main()

您将线程设置为守护进程,但您还需要保持“主”线程处于活动状态,以侦听信号。在Windows中,没有什么能像POSIX信号那样异步中断内核调度程序对象上的任何等待,在本例中,这是等待在
join
方法中获取锁的信号量。在内部,可以通过两种方式修改等待,以允许主线程中断。或者切换到使用
WaitForMultipleObjects
,并包含由
SIGINT
处理程序设置的事件(由C运行时的控制台控制处理程序调用)或者切换到使用可警报的
WaitForSingleObjectEx
wait,并让SIGINT处理程序队列APC来警报主线程。我不愿意提交修补程序来解决此问题,因为出于性能原因,使用本机条件变量而不是当前使用的基于信号量内核对象的模拟条件变量是有压力的。如果条件变量实现使用
SleepConditionVariableSRW
WakeConditionVariable
,控制台控制处理程序如何中断主线程并不明显。不管需要做什么,都可能需要进行一次大规模的重写。你将线程设置为守护进程,但你还需要让“主”线程保持活动状态,以侦听信号。没有什么比Windows中的POSIX信号更能异步中断对内核调度程序对象的任何等待,在本例中,它是等待在
join
方法中获取锁的信号量。在内部,可以通过两种方式修改等待,以允许主线程中断。或者切换到使用
WaitForMultipleObjects
,并包含由
SIGINT
处理程序设置的事件(由C运行时的控制台控制处理程序调用)或者切换到使用可警报的
WaitForSingleObjectEx
wait,并让SIGINT处理程序队列APC来警报主线程。我不愿意提交修补程序来解决此问题,因为出于性能原因,使用本机条件变量而不是当前使用的基于信号量内核对象的模拟条件变量是有压力的。如果条件变量实现使用
SleepConditionVariableSRW
WakeConditionVariable
,控制台控制处理程序如何中断主线程并不明显。无论需要做什么,都可能涉及到一次重大的重写。“daemon”对于Python线程有一个特定的含义,而OP并没有使
daemon=True
线程。无论如何,这是一个可能的解决办法。或者,连接可以在一个具有小超时的循环中实现(例如,
t.join(0.1)
),以允许主线程执行
SIGINT
处理程序(但如果在获取和释放锁之间中断了
join
),则容易出现错误)。您还可以通过
SetConsoleCtrlHandler
设置一个新的控制台控制处理程序,让它处理清理并在控制线程中退出进程,而不用担心主线程。@Fluffy,谢谢您的回答,它可以工作。一个注意事项是,传入时很糟糕,它会导致Python在我的机器上使用40%的CPU。如果将其替换为sleep(1),Python CPU使用率仅为2%,因此它是更好的选择。“daemon”对于Python线程有特定的含义,并且OP没有使daemon=True线程。无论如何,这是一个可能的解决办法。或者,连接可以在一个具有小超时的循环中实现(例如,
t.join(0.1)
),以允许主线程执行
SIGINT
处理程序(但如果在获取和释放锁之间中断了
join
),则容易出现错误)。您还可以通过
SetConsoleCtrlHandler
设置一个新的控制台控制处理程序,让它处理清理并在控制线程中退出进程,而不用担心主线程。@Fluffy,谢谢您的回答,它可以工作。一个注意事项是,传入时很糟糕,它会导致Python在我的机器上使用40%的CPU。如果将其替换为sleep(1),Python CPU使用率仅为2%,因此它是更好的选择。