PySide6/PyQT多线程之 多线程 与 线程池的模板(拿来即用)

news2024/11/17 15:36:03

描述

前言

关于PySide6/PyQT多线程系列的最后一篇。写这篇文章的动机是方便后续代码的直接复用。

本篇文章实际是水文,给出了 PySide6/PyQT的多线程以及线程池的基础使用模板,方便后面有需要时候直接拿来就用。


多线程

这里分两种情况来谈论,有返回值 与 无返回值。

无返回值

代码释义

定义 MyThread 的线程类,继承自 QThread
在构造函数中,接收一个函数 func 和其它参数 *args 和 **kwargs
并在 run() 方法中,调用传入的函数,并将参数传递给它。

定义 do_something() 的函数,它表示一个耗时的操作。

在主程序中,实例化MyThread 对象 thread,将 do_something 函数作为参数传递给它。
然后,通过调用 start() 方法启动线程,线程会自动执行 run() 方法中的任务。


# -*- coding: utf-8 -*-

import time
from PySide6.QtCore import (Qt, QThread)


# 自定义的工作任务类
class MyThread(QThread):
    def __init__(self, func, *args, **kwargs):
        super().__init__()
        self.func = func
        self.args = args
        self.kwargs = kwargs

    def run(self):
        self.func(*self.args, **self.kwargs)


def do_something():
    time.sleep(100)
    return '耗时操作'


if __name__ == '__main__':
    thread = MyThread(do_something)
    thread.start()

有返回值

有返回值,也分两种情况来讨论

  • 不推荐)使用线程对象的 wait() 方法等待子线程执行完毕,然后通过自定义的方法或属性来获取返回值
  • 推荐) 使用信号和槽机制进行线程间通信

不推荐

这种情况是不推荐的,不够线程安全,
在多线程编程中,共享数据可能存在竞争条件和线程安全性问题,从而引发线程安全性问题。

# -*- coding: utf-8 -*-

import time
from PySide6.QtCore import (Qt, QThread)


# 自定义的工作任务类
class MyThread(QThread):
    def __init__(self, func, *args, **kwargs):
        super().__init__()
        self.res = str()
        self.func = func
        self.args = args
        self.kwargs = kwargs

    def run(self):
        self.res = self.func(*self.args, **self.kwargs)


def do_something():
    time.sleep(100)
    return '耗时操作'


if __name__ == '__main__':
    thread = MyThread(do_something)
    thread.start()
    thread.wait()
    print(thread.res)

推荐


代码释义

整体流程如下:

  • 创建继承QThreadMyThead类,接收一个函数和不定长传参;重写了 run方法并在这里执行传递过来的函数和传参;
  • 创建继承自 QWidgetMainWindow 类,用于显示窗口和处理事件;
  • setup_ui 方法中设置窗口的标题、大小,并创建标签和按钮,并将它们添加到垂直布局中;
  • setup_thread 方法中创建 MyThread 线程对象,并连接它的 finish 信号到槽函数 thread_finished
  • do_something函数中模拟一个耗时的任务,并返回任务的结果;
  • thread_finished 槽函数中,接收到任务完成的信号后,将结果更新到标签上;
  • 运行程序后,窗口会显示一个标签和一个按钮。点击按钮后,耗时任务会在后台执行,执行完成后,结果会显示在标签上。


# -*- coding: utf-8 -*-

import time

from PySide6.QtCore import (QThread, Signal, Slot, QSize)
from PySide6.QtWidgets import (QApplication, QPushButton, QLabel, QVBoxLayout, QWidget)


class MyThread(QThread):
    finish = Signal(str)

    def __init__(self, func, *args, **kwargs):
        super().__init__()
        self.func = func
        self.args = args
        self.kwargs = kwargs

    def run(self):
        res = self.func(*self.args, **self.kwargs)
        # 任务完成后发出信号
        self.finish.emit(res)


def do_something():
    time.sleep(1)
    return 'the function execution completed!'


class MainWindow(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.setup_ui()
        self.button.clicked.connect(self.setup_thread)

    def setup_ui(self):
        self.setWindowTitle('demo')
        self.resize(QSize(250, 180))
        # 创建一个垂直布局
        layout = QVBoxLayout()
        # 创建一个标签
        self.label = QLabel('This is a label => ')
        layout.addWidget(self.label)
        # 创建一个按钮
        self.button = QPushButton('execute')
        layout.addWidget(self.button)
        # 将布局设置为主窗口的布局
        self.setLayout(layout)
        # 显示窗口
        self.show()

    def setup_thread(self):
        self.thread = MyThread(do_something)
        self.thread.finish.connect(self.thread_finished)
        self.thread.start()

    @Slot(str)
    def thread_finished(self, res):
        self.label.setText('This is a label => ' + res)


if __name__ == '__main__':
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec()

线程池

代码释义

MyWorker类继承自QRunnable,接收一个函数、一个信号和其他可变参数。在run方法中,它调用了传入的函数并将结果发射出信号。

do_something函数是一个模拟的耗时操作,它在执行完毕后返回一个字符串。

MainWindow类是窗口的主要部分,它创建了一个垂直布局,并添加了一个标签和一个按钮。点击按钮后,它创建一个MyWorker对象,并使用线程池启动这个线程。同时,它将信号与thread_finished槽函数连接起来,在线程完成后更新标签的文本。

# -*- coding: utf-8 -*-

import time

from PySide6.QtCore import (QRunnable, QThreadPool, Signal, Slot, QSize)
from PySide6.QtWidgets import (QApplication, QPushButton, QLabel, QVBoxLayout, QWidget)


class MyWorker(QRunnable):

    def __init__(self, func, signal, *args, **kwargs):
        super().__init__()
        self.func = func
        self.args = args
        self.kwargs = kwargs
        self.signal = signal

    def run(self):
        res = self.func(*self.args, **self.kwargs)
        # 任务完成后发出信号
        self.signal.emit(res)


def do_something():
    time.sleep(1)
    return 'the function execution completed!'


class MainWindow(QWidget):
    signal = Signal(str)

    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.thread_pool = QThreadPool()
        self.setup_ui()
        self.button.clicked.connect(self.setup_thread)

    def setup_ui(self):
        self.setWindowTitle('demo')
        self.resize(QSize(250, 180))
        # 创建一个垂直布局
        layout = QVBoxLayout()
        # 创建一个标签
        self.label = QLabel('This is a label => ')
        layout.addWidget(self.label)
        # 创建一个按钮
        self.button = QPushButton('execute')
        layout.addWidget(self.button)
        # 将布局设置为主窗口的布局
        self.setLayout(layout)
        # 显示窗口
        self.show()

    def setup_thread(self):
        worker = MyWorker(do_something, self.signal)
        self.thread_pool.start(worker)
        self.signal.connect(self.thread_finished)

    @Slot(str)
    def thread_finished(self, res):
        self.label.setText('This is a label => ' + res)


if __name__ == '__main__':
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec()

复用建议

在后续复用中,有以下注意事项

多线程线程池都需要注意的是:

  • run方法中考虑异常捕获;
  • 线程安全性: 在多线程环境下,要注意共享数据的线程安全性。

多线程

  • 线程的生命周期管理: 从创建到销毁的管理。确保在线程执行完毕后,适时释放线程资源,避免线程泄漏或过多的线程资源占用。

线程池

  • 线程池的最大线程数:可以通过修改setMaxThreadCount(n) 来设置线程池的最大线程数。
  • 线程销毁:可以考虑在线程执行完毕后进行销毁操作,以释放资源。可以通过在 MyWorker 的 run 方法中添加 self.setAutoDelete(True) 来实现。

但最重要的是根据实际情况来修改!

后话

本次分享到此结束,
see you~~🐱‍🏍🐱‍🏍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/548579.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[Hadoop]MapReduce与YARN

目录 大数据导论与Linux基础 Apache Hadoop、HDFS MapReduce MapReduce思想 MapReduce设计构思 MapReduce介绍 MapReduce官方实例 Map阶段执行流程 Reduce阶段执行流程 shuffle机制 YARN YARN介绍 YARN架构、组件 程序提交YARN交互流程 YARN资源调度器Scheduler…

IOS新建应用

一:Application App。普通app。Document App。打开是记事本类似App。Game。新建游戏相关app。RealityKit为新建一个打开摄像机,一个Ar立方体的应用。 SenceKit为有一架飞机旋转的游戏App。 SpirteKit为一个手指头按上会出一个手指特效的应用。 Metal为一…

【IDEA使用指南】使用Hibernate框架的Java项目,如何通过数据库表自动生成实体模型?

文章目录 【IDEA使用指南】使用Hibernate框架的Java项目,如何通过数据库表自动生成实体模型?步骤1:找到并打开“Persistence”工具栏。步骤2:找到并打开“Import Database Schema” 窗口。步骤3:配置数据源信息步骤4:查看自动生成的实体模型。【IDEA使用指南】使用Hibern…

如何在IDEA中显示时序图

如何在IDEA中显示时序图 有时候,我们想要了解代码的运行过程的时候,想要看到方法的调用流程。 这个时候就希望有一个时序图可以看,但是人工来画时序图太麻烦了,有没有办法在IDEA中直接生成呢? 当然是可以的。 这里…

Access denied for user ‘root‘@‘localhost‘ (using password:YES) 解决方案

文章目录 问题描述解决方案: 问题描述 Access denied for user ‘root’‘localhost’:拒绝用户’root’localhost’的访问。 出现这个报错语句的一般原因是输入了错误的密码,也有可能是是root帐户默认不开放远程访问权限。 相关的解决方法是重新设置…

【Linux】sysfs文件系统

【Linux】sysfs文件系统 前言 一、sysfs文件系统 1.1 sysfs系统是什么 1.2 sysfs的运行机制原理 二、sysfs中重要的结构体 2.1 kobject和kset之间的关系 2.2 kobject结构体 2.3 kset结构体 前言 重要的环节:带着问题不断前进 sysfs文件系统是什么sysf文件系…

YOLOv5 实例分割入门

介绍 YOLOv5 目标检测模型以其出色的性能和优化的推理速度而闻名。因此,YOLOv5 实例分割模型已成为实时实例分割中最快、最准确的模型之一。 在这篇文章中,我们将回答以下关于 YOLOv5 实例分割的问题: YOLOv5检测模型做了哪些改动,得到了YOLOv5实例分割架构?使用的 Prot…

RTC实时时钟源码分析

1.先来看一下RTC的配置过程 2.RTC源码讲解 我们的工程中加入了 rtc.c 源文件和 rtc.h头文件,同时,引入了 stm32f10x_rtc.c 和 stm32f10x_bkp.c 库文件。 说明,首先是 RTC_Init,其代码如下: //实时时钟配置 //初始化…

UI自动化测试遇弹窗怎么办?这个解决方法你get到了没?

目录 引言 弹窗的种类: APP内的业务弹窗 弹窗处理 watcher的使用 实战案例 软件测试技术的准备和建议 一、测试基础 二、Linux必备知识 三、Shell脚本 四、互联网程序原理 五、MySQL数据库 六、抓包工具 七、接口测试工具 八、Web自动化测试Java&Python 九…

关于C语言的杂记5

文章目录 引入正文内部函数与外部函数相关数组的知识点数组的初始化测试一维数组在内存中存储的地址:遍历二维数组的值测试二维数组的地址(观察内存情况)数组下标为0开始的由来 两个数交换位置的三种方法 引入 写在前面:关于C语言这部分内容,…

msys2 pacman 安装 ncurses-devel 解决 make menuconfig 问题

问题描述 windows 下使用 msys2 环境,可以开发编译一些 Linux 下的软件包,一般Linux 下的软件包,需要安装 PC 平台的gcc、gcc交叉编译工具链,如 arm的,以及一些常用的 软件包,如 python 等 有一个软件包&a…

【工具】Ubuntu 非root用户 安装openssl

文章目录 openssl 下载 & 解压指定安装路径编译安装配置环境变量验证是否安装成功 openssl 下载 & 解压 openssl 下载地址 或者 https://www.openssl.org/source/openssl-1.1.1l.tar.gz 上传到服务器 解压 tar -zxvf openssl-1.1.1l.tar.gz切换到openssl-1.1.1l目…

maven-resources-plugin详解

目录 一、什么场景会用到?二、他有什么作用?三、插件常用配置1、字符集编码2、resources相关的配置2.1、resources配置结构2.2、resources默认配置2.2.1、maven超级pom默认配置2.2.2、spring-boot对resources插件的默认配置2.2.3、resources最终生效的配…

2023年最新VMware 17+虚拟机详细配置安装【程序员使用指南】!!

文章目录 Vmware版本选择17Pro安装自定义安装填写对应的许可证正式安装虚拟机进行对应的配置配置镜像文件选择对应的语言:到这个界面,选择中文 安装结束连接对应的xshell Vmware版本选择17Pro安装 ● 最开始从这里出发 自定义安装 ● 记得自定义在自…

TikTok选品,什么产品在TikTok最受欢迎?

TikTok是当下的海外社交媒体推广新风口已经有目共睹,与此同时跨境商家们或许都面临着同样的问题,就是TikTok要怎么选品,什么产品才会比较受欢迎。俗话说:七分靠选品,三分靠运营。选品选对了,运营也就事半功…

chatgpt赋能Python-python3_decode函数

Python3 decode函数 - 解码你的数据 编程领域中,字符串是一个不可避免的概念,他们构成了我们生活中逻辑化和技术实现化的重要组成部分。不仅如此,字符串的加载和使用也对程序的性能产生了重大的影响。在这篇文章中,我们将重点讨论…

现在有什么基于vue3.0的优秀开源项目呢?

前言 以下是一些github上一些基于vue3.0的优秀开源项目,可以自己选择一些去练一下手,废话少说,直接进入正题---- 1、 vue-manage-system Star: 16k 是一个基于 Vue3 和 Element Plus 的后台管理系统解决方案,它提供了一系列的通…

电脑找不到msvcr110.dll怎么办?电脑msvcr110.dll丢失怎么解决?

在使用某些软件或游戏时,有时会出现找不到msvcr110.dll文件的错误提示,这会导致程序无法正常运行。这个问题通常是由于缺少Visual C msvcr110.dll引起的。下面是解决这个问题的几个方法: msvcr110.dll的解决方法一 直接使用dll修复程序进行修…

videojs扩展方法,自定义功能

8版本不支持extend,8支持es6扩展 videojsextend

DeepGPS: Deep Learning Enhanced GPS Positioning in Urban Canyons

DeepGPS: Deep Learning Enhanced GPS Positioning in Urban Canyons IEEE TMC|深度学习增强的城市峡谷GPS定位 https://github.com/bducgroup/DeepGPS 文章目录 DeepGPS: Deep Learning Enhanced GPS Positioning in Urban CanyonsAbstract1 INTRODUCTION2 BACKGRO…