Python使函数始终使用线程而不调用thread.start()

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 连接。

Mis*_*agi 6

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)