【问题标题】:Killing a python thread杀死一个python线程
【发布时间】:2022-11-29 16:10:35
【问题描述】:

我想通过设置一个事件以某种方式从我的 GUI 应用程序中杀死一个正在运行的线程,但是我不能在我的线程中使用 for 循环所以我需要一些其他的解决方案来检查事件

我有以下情况。 在 tkinter gui 中,当我单击一个按钮时,我启动一个线程并设置一个全局变量。

self.thread = StoppableThread(caller=self)
self.thread.start()
is_running = 1

当我下次单击按钮时,我检查全局变量状态,如果它已经设置,我发送一个停止请求:

if is_running:
    is_running = 0
    self.thread.stop()

这是我的线程类:

import threading
from time import sleep


class StoppableThread(threading.Thread):
    def __init__(self, caller=None):
        super(StoppableThread, self).__init__()
        self._stop_event = threading.Event()
        self.caller = caller

    def stop(self):
        self._stop_event.set()

    def stopped(self):
        return self._stop_event.is_set()

    def run(self) -> None:
        while True:
            # check for stop
            if self.stopped():
                break

            for i in range(10):
                sleep(1)
                print('Test')

            print('Worker done')
            break

如果我将 while 更改为 for 循环,则一切正常,但因为在我的业务逻辑中的这一点上,我没有任何可循环的东西,因为我需要以某种方式检查 self.stopped() 的不同状态。有没有办法在 while 循环中检查它?

或者我怎样才能做到这一点?我尝试使用进程而不是线程,但由于错误“进程无法腌制 tkinter”而无法正常工作。

感谢您的任何帮助

【问题讨论】:

  • 您只需在开始时检查一次 stopped 标志,因为在第一个循环之后您是 break。只需删除 for 语句(但保留内容),并删除 print('Worker done')break
  • 由于 while 循环末尾的 break,while 循环仅运行一次迭代。此外,最好发布按您所说的那样工作的 for 循环“如果我将 while 更改为 for 循环,一切正常”.
  • 如果您至少描述您在此线程中正在做什么,以指出有效的解决方案,这将有所帮助。当您的问题已写好时,您需要做的就是删除 break 语句并将 print('Worker done') 从您的 while 循环中移出封闭空间。由于您解析了一个 caller 并且您包含的错误指出它是您正在解析的一个小部件,因此即使进行了这些更改,您的体系结构仍然很可能会中断。
  • 哦,是的,删除中断是个好点,对不起,但仍然没有停止。
  • @Thingamabobs 我不想在这里复制整个线程处理。但这里有一个描述。启动线程后,我从数据库中读取了一些数据并将它们传递给另一个处理类。在这个类中,我做很长时间的处理任务,向 API 发送请求等等。有些情况我想从这里突破并且不要等到例如所有 20 个请求(每小时 1 个请求)完成。

标签: python python-3.x multithreading tkinter


【解决方案1】:

这个循环将永远运行,直到你设置标志:

    def run(self):
        while not self.stopped():
            sleep(1)
            print('Test')

你实际上并不需要一个事件。一个简单的布尔值就可以了。

跟进

这是一个基于您的代码的示例,展示了它是如何工作的:

import threading
from time import sleep

class StoppableThread(threading.Thread):
    def __init__(self, caller=None):
        super(StoppableThread, self).__init__()
        self._stop_event = False
        self.caller = caller

    def stop(self):
        self._stop_event = True

    def stopped(self):
        return self._stop_event

    def run(self) -> None:
        while not self.stopped():
            sleep(1)
            print('Test')
        print("exited")

thread = StoppableThread(caller=None)
thread.start()
sleep(5)
thread.stop()
sleep(1)
print("program ending")

【讨论】:

  • 您是否阅读了问题或为什么您提出不同的建议而不提出替代方案?
  • 你读过这个问题了吗?他抱怨说在使用 while 循环时他无法停止线程。他不能这样做的原因是他错误地使用了while 循环。我展示了如何正确使用它。
  • 当我下次点击按钮时,我检查全局变量状态,如果它已经设置,我发送一个停止请求-- 你提出了一个简单的布尔值,它本​​身不是线程安全的。为什么要这么做 ? python 在你玩的技术上有什么不同吗?
  • 我试过了。将 self._stop_event 更改为 False 并将 stop() 设置为 True 并按照您的建议进行检查。但这里是输出: Test 0 Test 1 Stop requested Test 2 Test 3 Test 4
  • 那你做错了。我已经更新了示例。
猜你喜欢
  • 1970-01-01
  • 2011-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多