Pau*_*ink 2 python multithreading pyqt5
本质上我想做的是有一个函数,每当调用它时,它都会在单独的线程上执行。我不想调用 thread.start(),因为这会立即执行它。
我有以下 python 脚本。我的 GUI 使用 PyQt5。每当按下按钮时,我想在单独的线程上执行长时间运行的函数。这是代码:
from PyQt5 import QtWidgets, uic
import time
def longRunningFunction():
time.sleep(10)
app = QtWidgets.QApplication([])
dlg = uic.loadUi("app.ui")
dlg.button_to_click.clicked.connect(longRunningFunction)
dlg.show()
app.exec()
Run Code Online (Sandbox Code Playgroud)
当我向程序添加线程时,该函数在 thread.start() 上执行。下面是添加了线程的代码:
from PyQt5 import QtWidgets, uic
import time
import threading
def longRunningFunction():
time.sleep(10)
app = QtWidgets.QApplication([])
dlg = uic.loadUi("app.ui")
dlg.button_to_click.clicked.connect(longRunningFunction)
thread = threading.Thread(target=longRunningFunction)
thread.start()
dlg.show()
app.exec()
Run Code Online (Sandbox Code Playgroud)
使该函数在调用时始终使用单独的线程,以便 GUI 不会冻结的最佳方法是什么?该函数在运行时将被连续调用,每分钟多次。这个函数也将比示例复杂得多。它将使用其他自定义 python 脚本中的多种方法,并且还运行一个 websocket 连接。
TLDR:定义一个装饰器,在调用函数时创建并启动线程。
增强函数/类的功能通常使用装饰器来完成。这是一个可调用函数,它接收函数/类,并将其包装或替换为所需的功能。可以使用@
函数/类定义的语法或稍后通过常规调用来应用装饰器。
此用例的简单装饰器仅接收可调用对象 ( func
) 并将其包装在一个新函数中,该函数使用线程来运行可调用对象。
import threading
import functools
def threaded(func):
"""Decorator to automatically launch a function in a thread"""
@functools.wraps(func)
def wrapper(*args, **kwargs): # replaces original function...
# ...and launches the original in a thread
thread = threading.Thread(target=func, args=args, kwargs=kwargs)
thread.start()
return thread
return wrapper
Run Code Online (Sandbox Code Playgroud)
使用语法定义新函数时可以应用此装饰器@
:
@threaded
def long_running_function():
time.sleep(10)
print("Done")
long_running_function()
print("started")
Run Code Online (Sandbox Code Playgroud)
如果函数已经定义或者必须在有或没有线程的情况下使用,则也可以通过调用它来应用装饰器:
dlg.button_to_click.clicked.connect(threaded(longRunningFunction))
Run Code Online (Sandbox Code Playgroud)