【问题标题】:Python3 Threading: Why are 2 threads active when I have only started one?Python3 线程:为什么我只启动了一个线程时有 2 个线程处于活动状态?
【发布时间】:2021-08-23 14:30:10
【问题描述】:

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

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()

【问题讨论】:

    标签: python multithreading kivy


    【解决方案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_thread 设置为None。您可能还想调整show_running_threads() 中的print(),以便在self.my_threadNone 时打印False

    【讨论】:

    • show_running_threads,正如您所怀疑的那样,只是为了调试。我已经按照您的建议进行了更改。我需要付出更多努力来理解 join() 并将变量设置为 None。它说我不应该但谢谢你。
    猜你喜欢
    • 2010-10-11
    • 2013-04-21
    • 1970-01-01
    • 1970-01-01
    • 2011-09-09
    • 2014-10-03
    • 2015-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多