0

有人可以向我解释一下,当我只设置一个线程时,为什么有 2 个线程(Thread-1 和 Thread-2)处于活动状态:(my_thread)?Thread-1 似乎一直为 True 并且永远不会变为 False。如何更正我的代码,以便在按下“停止”按钮时只有一个线程处于活动状态并变为 False。这是我使用 Threading 编写的第一个程序,我不明白它。

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.uix.label import Label
from time import sleep
import threading


class MyApp(BoxLayout):
    def __init__(self, **kwargs):
        super(MyApp, self).__init__(**kwargs)
        self.orientation = 'horizontal'
        self.running=False
        
        self.btn = Button(text='Start', size_hint_x=.1)        
        self.lbl = Label(size_hint_x=.9)
        
        self.add_widget(self.btn)
        self.btn.bind(on_press = self.start_stop)
        self.add_widget(self.lbl)

    def do_something(self,n):
        while self.running:
            self.lbl.text = str(n)
            sleep(.5)
            n += 1
        else:
            self.show_running_threads()
                
    def start_stop(self,event):
        if self.running:
            self.btn.text = 'Start'
        else:
            self.btn.text = 'Stop'
            self.running = False            

        self.running = not self.running 
        self.my_thread = threading.Thread(target = self.do_something,args = (0,))
        self.my_thread.start()

    def show_running_threads(self):
        runningThreads = []
        for thread in threading.enumerate():
            runningThreads.append(thread.name)
            self.lbl.text = 'Running threads: ' + str(runningThreads) +\
                            '\n my_thread running = ' + str(self.my_thread.is_alive())
            
        print(runningThreads)
        
        if self.my_thread.is_alive():
            print('my_thread still running')
        else:
            print('my_thread cancelled\n','-'*80,sep='')
        
class MyLayout(App):
    def build(self):
        return MyApp()
      
        
if __name__ == '__main__':
    MyLayout().run()
4

1 回答 1

1

你在这里有几个问题。要回答您的直接问题,您最终使用两个线程的原因是因为start_stop()无论请求哪个操作都会创建一个新线程。这是一个替代方案,简化了一些逻辑:

    def do_something(self,n):
        while self.running:
            self.lbl.text = str(n)
            sleep(.5)
            n += 1

    def start_stop(self,event):
        if not self.running:
            self.running = True
            self.btn.text = 'Stop'
            self.my_thread = threading.Thread(target = self.do_something,args = (0,))
            self.my_thread.start()
        else:
            self.running = False
            self.my_thread.join()
            self.my_thread = None
            self.btn.text = 'Start'
            self.show_running_threads()

调用join()等待退出线程是个好主意,这样您就可以显示正确的状态,而不必担心线程是否真正完成了while循环并退出。

一个相关的问题是您是show_running_threads()从线程内部调用的,因此它永远不会报告线程已被取消,因为此时线程仍然处于活动状态。我把它移到了start_stop.

我不确定其中的大部分逻辑show_running_threads()是否仅用于调试,所以我没有修改它,但您至少可能想要更改:

if self.my_thread.is_alive():

至:

if self.my_thread and self.my_thread.is_alive():

作为更改start_stop()设置self.my_threadNone前一个线程结束的时间。您可能还需要调整print()inshow_running_threads()以便Falseself.my_threadis时打印None

于 2021-08-23T17:58:24.733 回答