使用 Tkinter 中的按钮终止线程

VaF*_*ncy 0 python multithreading tkinter multiprocessing raspberry-pi

在我的 GUI 代码中,我尝试通过单击一个按钮来同时运行循环 1 和循环 2。因此,我曾经Thread实现过这一点。但我也尝试通过单击另一个按钮来阻止它,但失败了。在stackoverflow上搜索后,我发现没有直接杀死 的方法Thread。这是代码的一部分:

def loop1():
    while True:
        call (["raspivid -n -op 150 -w 640 -h 480 -b 2666666.67 -t 5000 -o test.mp4"],shell=True)
        call (["raspivid -n -op 150 -w 640 -h 480 -b 2666666.67 -t 5000 -o test1.mp4"],shell=True)

def loop2():
    while True:
        call (["arecord -D plughw:1 --duration=5 -f cd -vv rectest.wav"],shell=True)
        call (["arecord -D plughw:1 --duration=5 -f cd -vv rectest1.wav"],shell=True)

def combine():
    Thread(target = loop1).start()
    Thread(target = loop2).start()

def stop():
    Thread(target = loop1).terminate()
    Thread(target = loop2).terminate()
Run Code Online (Sandbox Code Playgroud)

我尝试用这两个按钮来控制它。

btn1 = Button(tk, text="Start Recording", width=16, height=5, command=combine)
btn1.grid(row=2,column=0)
btn2 = Button(tk, text="Stop Recording", width=16, height=5, command=stop)
btn2.grid(row=3,column=0)
Run Code Online (Sandbox Code Playgroud)

我希望loop1和loop2可以停止button2。显然没有terminatein Thread. 所以我用了另一种方法Process。这是代码:

from subprocess import call
from multiprocessing import Process
def loop1():
    while True:
        call (["raspivid -n -op 150 -w 640 -h 480 -b 2666666.67 -t 5000 -o test.mp4"],shell=True)
        call (["raspivid -n -op 150 -w 640 -h 480 -b 2666666.67 -t 5000 -o test1.mp4"],shell=True)
def loop2():
    while True:
        call (["arecord -D plughw:1 --duration=5 -f cd -vv rectest.wav"],shell=True)
        call (["arecord -D plughw:1 --duration=5 -f cd -vv rectest1.wav"],shell=True)
if __name__ == '__main__':
    Process(target = loop1).start()
    Process(target = loop2).start()
Run Code Online (Sandbox Code Playgroud)

但是这个程序在我运行之后就立即结束了。我知道 中有terminate函数Process。但我不知道如何使用它。

eba*_*arr 6

一个潜在的解决方案将使用Events。另外,制作 GUI 时的一个好的经验法则是使用对象。

from threading import Thread,Event
from subprocess import call

class Controller(object):
    def __init__(self):
        self.thread1 = None
        self.thread2 = None
        self.stop_threads = Event()

    def loop1(self):
        while not self.stop_threads.is_set():
            call (["raspivid -n -op 150 -w 640 -h 480 -b 2666666.67 -t 5000 -o test.mp4"],shell=True)
            call (["raspivid -n -op 150 -w 640 -h 480 -b 2666666.67 -t 5000 -o test1.mp4"],shell=True)

    def loop2(self):
        while not self.stop_threads.is_set():
            call (["arecord -D plughw:1 --duration=5 -f cd -vv rectest.wav"],shell=True)
            call (["arecord -D plughw:1 --duration=5 -f cd -vv rectest1.wav"],shell=True)

    def combine(self):
        self.stop_threads.clear()
        self.thread1 = Thread(target = self.loop1)
        self.thread2 = Thread(target = self.loop2)
        self.thread1.start()
        self.thread2.start()

    def stop(self):
        self.stop_threads.set()
        self.thread1.join()
        self.thread2.join()
        self.thread1 = None
        self.thread2 = None
Run Code Online (Sandbox Code Playgroud)

这样你的按钮调用就会变成这样:

control = Controller()
btn1 = Button(tk, text="Start Recording", width=16, height=5, command=control.combine)
btn1.grid(row=2,column=0)
btn2 = Button(tk, text="Stop Recording", width=16, height=5, command=control.stop)
btn2.grid(row=3,column=0)
Run Code Online (Sandbox Code Playgroud)