具有线程或多处理的 Tkinter CPU 密集型任务

Posted

技术标签:

【中文标题】具有线程或多处理的 Tkinter CPU 密集型任务【英文标题】:Tkinter CPU intensive tasks with threading or multiprocessing 【发布时间】:2021-08-15 04:58:58 【问题描述】:

我有一个 tkinter 应用程序,它通过单击按钮启动 CPU 密集型任务,并且任务的进度应该在进度条上更新。由于 Python 的 GIL(全局解释器锁)(据我所知),使用 threading.Thread 类不起作用。我尝试使用multiprocessing.Process 类,但它似乎也不起作用。我不能将回调传递给创建的新进程,以便它调用该函数来更新进度条吗?

请看下面的例子:

from tkinter import Tk, Button
from threading import Thread
from tkinter.ttk import Progressbar
from tkinter.constants import HORIZONTAL
from multiprocessing import Process
import math

root = Tk()
root.title("Multiprocessing Demo")
root.geometry("500x400")

def cpu_intensive_task():
    math.factorial(210000)
    progress_bar['value'] = 50
    math.factorial(210000)
    progress_bar['value'] = 100
    root.update_idletasks()
    print("Done")
    

progress_bar = Progressbar(
    root, orient=HORIZONTAL, length=500, mode="determinate"
)

progress_bar.pack(pady=20)

start_btn = Button(
    root,
    text="Start",
    command=Thread(target=cpu_intensive_task).start, # This freezes the GUI
    # command=Process(target=cpu_intensive_task).start, # This gives the mentioned error below

)
start_btn.pack(pady=20)

root.mainloop()

使用 Process 实例时的错误消息:

XIO:  fatal IO error 25 (Inappropriate ioctl for device) on X server ":0"
      after 1266 requests (1266 known processed) with 0 events remaining.
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
python3: xcb_io.c:269: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.
[1]    193933 abort (core dumped)  python3 multi.py

使用共享队列并对其进行轮询似乎也不是一个好的解决方案,因为我们必须在循环中不断地轮询队列,并且事件最多可能会延迟两次轮询之间的时间。有没有办法在不进行轮询的情况下实现这一目标?

【问题讨论】:

创建一个启动线程或进程的函数。然后将此函数作为命令传递给按钮。 【参考方案1】:

看起来,如果你想从你的 cpu 获取一些信息:

import psutil
cpu_freq = psutil.cpu_freq()    # shows your current cpu freq // if you are on linux
                                # you can use // sensors_temperatures() to show the cpu temp
print(cpu_freq)

【讨论】:

以上是关于具有线程或多处理的 Tkinter CPU 密集型任务的主要内容,如果未能解决你的问题,请参考以下文章

如何理解CPU密集型 和 I/O密集型

如何确定线程池的大小?

如何理解CPU密集型 和 I/O密集型

线程池线程数处理

设置线程池大小 · 贰白

多线程应用那个开多少线程合适