1

我正在尝试制作一个以迭代方式处理繁重计算负载的程序。我希望能够中断程序并重新启动。

我使用 Tkinter 构建了一个简单的 GUI,以允许使用“after_cancel”中断迭代循环。这在计算负载较低的测试中效果很好,但在计算负载较高的情况下,程序不会响应旨在执行“after_cancel”的按钮单击。

为简单起见,我已将程序替换为斐波那契。效果是一样的(一段时间后)。

我该如何设计它以使“停止”按钮保持响应?

这是代码:

from tkinter import *
import time

def fibonacci(n):
    if n == 0:
        return 0
    if n == 1:
        return 1
    return fibonacci(n - 1) + fibonacci(n - 2)


class App:

    def __init__(self, master):

        self.frame = Frame(master)
        self.frame.pack(expand=1, fill=BOTH)
        self.master = master

        self.quitter = Button(self.frame, text="Quit", fg="red", command=self.master.destroy)
        self.quitter.pack(side=LEFT)

        self.starter = Button(self.frame, text="Start", command=self.start)
        self.starter.pack(side=LEFT)

        self.stopper = Button(self.frame, text="Stop", command=self.stop)
        self.stopper.pack(side=LEFT)

        self.counter = 0

    def start(self):
        print((fibonacci(self.counter)))
        self.counter += 1
        self.afterid = self.master.after(1, self.start)

    def stop(self):
        print('Stop')
        self.master.after_cancel(self.afterid)


root = Tk()
app = App(root)
root.mainloop()
4

2 回答 2

3

如果您从小部件回调中调用您的fibonacci函数,它将在您的 GUI 线程上运行。为避免冻结您的 GUI,请fibonacci在单独的线程上运行并设置一个标志以停止其执行:

from tkinter import *
import threading
import time


def fibonacci(n):
    if n == 0:
        return 0
    if n == 1:
        return 1
    return fibonacci(n-1) + fibonacci(n-2)


class App:

    def __init__(self, master):
        self.frame = Frame(master)
        self.frame.pack(expand=1, fill=BOTH)
        self.master = master

        self.quitter = Button(self.frame, text="Quit", fg="red", command=self.master.destroy)
        self.quitter.pack(side=LEFT)

        self.starter = Button(self.frame, text="Start", command=self.start)
        self.starter.pack(side=LEFT)

        self.stopper = Button(self.frame, text="Stop", command=self.stop)
        self.stopper.pack(side=LEFT)

        self.counter = 0
        self.running = False

    def start(self):
        self.running = True
        threading.Thread(target=self.start_fibonacci).start()

    def start_fibonacci(self):
        while self.running:
            print(fibonacci(self.counter))
            self.counter += 1
            time.sleep(1)

    def stop(self):
        self.running = False
        print('Stop')


if __name__ == "__main__":
    root = Tk()
    root.title("Fibonacci")
    app = App(root)
    root.mainloop()
于 2013-04-14T19:56:19.507 回答
1

在 mainprog 函数中,您计算​​一次斐波那契,然后将警报回调注册为 self.mainprog,在 1 毫秒后调用。换句话说,每次调用斐波那契函数之间都有一个间隔时间。并且您的 stopprog 按钮只能在控制权空闲时在间隔时间内响应您。

在高计算负载下,您的任务始终保留执行权(在一次斐波那契函数调用中)。结果,没有按钮可以响应您。

您最好以多线程或多进程的方式实现您的品味(例如斐波那契计算)以避免此问题。

于 2013-04-14T18:50:40.300 回答