在运行线程中设置变量以停止线程

0 投票
1 回答
1502 浏览
提问于 2025-04-17 22:05

我有一个对象叫做 cooker,它的 run() 方法会启动一个新的线程,叫做 cookingThread。我想在5秒后通过设置一个变量 stopThread 来停止这个 cookingThread,该怎么做呢?

我尝试用 cooker.toggle() 来先启动这个线程,但是下一个 cooker.toggle() 却无法停止这个线程。

下面的代码给我报了一个错误,内容是 NameError: global name 'cookingThread' is not defined,意思是说找不到 cookingThread 这个名字。

import threading
import time

class Cooker(object):

    def __init__(self, recipe):
        self.active = False
        self.recipe = recipe

    def toggle(self):
        if not self.active:
            self.active = True
            self.run()

        else:
            self.active = False
            # How can this stop flag be passed into the running thread?
            cookingThread.stopThread = True


    def run(self):
        cookingThread = CookingThread(self.recipe)
        cookingThread.start()

CookingThread

class CookingThread(threading.Thread):

    def __init__(self, recipe):
        super(CookingThread, self).__init__()
        self.recipe = recipe
        self.stopThread = False

    def run(self):
        for i in range(self.recipe):
            # Check if we should stop the thread
            if self.stopThread:
                return
            else:
                print 'Cooking...'
                time.sleep(1)

Main

cooker = Cooker(10)
cooker.toggle()    # Starts the thread

time.sleep(5)
cooker.toggle()    # Stops the thread (does not work)

1 个回答

1

问题在于,cookingThread 这个变量只在 Cooker.run() 方法内部可用。错误提示是说你需要把它声明为全局变量,这样才能在所有方法中访问。但这样做并不是一个好的编程习惯。

你可以尝试以下方法:

import threading
import time

class Cooker(object):

    def __init__(self, recipe):
        self.active = False
        self.recipe = recipe

    def toggle(self):
        if not self.active:
            self.active = True
            self.run()

        else:
            self.active = False
            # How can this stop flag be passed into the running thread?
            self.cookingThread.stop()


    def run(self):
        self.cookingThread = CookingThread(self.recipe)
        self.cookingThread.start()

然后把 CookingThread 改成这样:

class CookingThread(threading.Thread):

    def __init__(self, recipe):
        super(CookingThread, self).__init__()
        self.recipe = recipe
        self.stopThread = False

    def run(self):
        for i in range(self.recipe):
            # Check if we should stop the thread
            if self.stopThread:
                return
            else:
                print 'Cooking...'
                time.sleep(1)

    def stop(self):
        self.stopThread = True

一般来说,在进行面向对象编程时,尽量不要直接访问字段,比如 cookingThread.stopThread。应该使用一个方法,比如 stop,来进行修改。

撰写回答