pyqt多任务执行

import sys
import time

from PyQt5.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QWidget,
							 QComboBox, QTabWidget, QTableWidget, QTableWidgetItem)
from PyQt5.QtCore import Qt, pyqtSignal, QObject, QTimer
import threading

from PyQt5.QtWidgets import QApplication, QMainWindow, QTextEdit
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLineEdit, QPushButton
from PyQt5.QtWidgets import (QApplication, QMainWindow, QVBoxLayout,
							 QWidget, QTextEdit, QPushButton, QHBoxLayout)

import queue


class Conn(QObject):
	receivedSignal = pyqtSignal(str)
	finishedSignal = pyqtSignal()  # 添加完成信号

	def __init__(self):
		super(Conn, self).__init__()
		self.continued = True
		self._running = True
		self._thread = None
		self._count = 0
		self._lock = threading.Lock()  # 添加锁确保线程安全

	def open(self):
		self._thread = threading.Thread(target=self.read)
		self._thread.setDaemon(True)
		self._thread.start()
		return self  # 返回自身以便链式调用

	def read(self):
		print(f"Conn.read线程启动,线程ID: {threading.get_ident()}")
		read_count = 0
		while self._running:
			with self._lock:
				if self.continued:
					read_count += 1
					msg = f"read data {read_count}"
					print(f"Conn.read准备发送信号: {msg}")
					self.receivedSignal.emit(msg)
					print(f"Conn.read已发送信号: {msg}")
			time.sleep(0.5)  # 降低频率,便于观察

		print("Conn.read线程结束")
		self.finishedSignal.emit()  # 线程结束时发出信号

	def login(self):
		print("login start")
		with self._lock:
			self.continued = False
		for i in range(3):
			time.sleep(1)
			print(f"login step {i + 1}")
			self.receivedSignal.emit(f"login step {i + 1}")
		with self._lock:
			self.continued = True
		print("login end")

	def stop(self):
		"""停止读取线程"""
		print("Conn.stop被调用")
		self._running = False
		if self._thread and self._thread.is_alive():
			self._thread.join(timeout=1)

	def is_alive(self):
		"""检查线程是否存活"""
		return self._thread and self._thread.is_alive()


class Task(QObject):
	logSignal = pyqtSignal(str)
	taskFinished = pyqtSignal()

def __init__(self, idx=1, parent=None):
    super(Task, self).__init__(parent)
    self.idx = idx
    self.conn = None  # 保存Conn对象的引用
    self._task_thread = None  # 保存任务线程的引用

def show_task_info(self, str_msg):
    print(f"Task{self.idx}.show_task_info收到: {str_msg}")
    self.logSignal.emit(f"任务{self.idx}: {str_msg}")

def run_task(self):
    """运行单个任务 - 这个方法会在单独的线程中执行"""
    print(f"任务{self.idx}线程启动,线程ID: {threading.get_ident()}")

    # 创建并保存Conn对象
    self.conn = Conn()
    # 连接信号 - 这会跨线程工作
    self.conn.receivedSignal.connect(self.show_task_info)

    # 打开连接,启动读取线程
    print(f"任务{self.idx}: 打开连接")
    self.conn.open()

    # 等待一会儿,让read线程开始工作
    print(f"任务{self.idx}: 等待2秒让read线程开始")
    for i in range(4):  # 等待2秒,每0.5秒打印一次
        time.sleep(0.5)
        print(f"任务{self.idx}: 等待中...{i + 1}")

    # 执行登录操作
    print(f"任务{self.idx}: 开始登录操作")
    self.conn.login()

    # 等待登录后的数据读取
    print(f"任务{self.idx}: 等待3秒观察登录后的读取")
    for i in range(6):  # 等待3秒
        time.sleep(0.5)
        print(f"任务{self.idx}: 登录后等待...{i + 1}")

    # 停止Conn
    print(f"任务{self.idx}: 停止连接")
    self.conn.stop()

    # 稍微等待确保线程完全停止
    time.sleep(0.5)

    print(f"任务{self.idx}线程结束")
    self.taskFinished.emit()


class TaskManager(QObject):
	taskLogSignal = pyqtSignal(str)
	allTasksFinished = pyqtSignal()

def __init__(self):
    super().__init__()
    self.task_queue = queue.Queue()
    self.current_task = None
    self.running = False
    self.tasks = []  # 保存所有任务对象的引用

def add_task(self, task):
    """添加任务到队列"""
    self.task_queue.put(task)

def start(self):
    """开始执行任务队列"""
    if not self.running:
        self.running = True
        self.taskLogSignal.emit("任务队列开始执行")
        # 使用QTimer确保在GUI线程中开始执行
        QTimer.singleShot(0, self._execute_next_task)

def _execute_next_task(self):
    """执行下一个任务"""
    if not self.task_queue.empty():
        task = self.task_queue.get()
        self.tasks.append(task)  # 保存任务引用
        self.taskLogSignal.emit(f"开始执行任务 {task.idx}")

        # 连接任务的完成信号
        task.taskFinished.connect(self._on_task_finished)

        # 在新线程中执行任务
        task._task_thread = threading.Thread(target=task.run_task)
        task._task_thread.setDaemon(True)
        task._task_thread.start()
    else:
        self.running = False
        self.taskLogSignal.emit("所有任务执行完成")
        self.allTasksFinished.emit()

def _on_task_finished(self):
    """任务完成后的回调"""
    # 在GUI线程中继续下一个任务
    QTimer.singleShot(0, self._execute_next_task)


class MainWindow(QMainWindow):
	def __init__(self):
		super().__init__()
		self.task_manager = TaskManager()
		self.initUI()

    # 连接任务管理器的信号
    self.task_manager.taskLogSignal.connect(self.show_info)
    self.task_manager.allTasksFinished.connect(self.on_all_tasks_finished)

def initUI(self):
    # 设置窗口标题和大小
    self.setWindowTitle('串行任务执行示例')
    self.setGeometry(300, 300, 600, 400)

    # 创建中央部件
    central_widget = QWidget()
    self.setCentralWidget(central_widget)

    # 创建主布局
    main_layout = QVBoxLayout()

    # 创建文本编辑框
    self.text_edit = QTextEdit()
    self.text_edit.setPlaceholderText('任务执行日志...')

    # 创建按钮
    self.start_button = QPushButton('开始串行任务')
    self.clear_button = QPushButton('清空日志')

    # 创建按钮布局
    button_layout = QHBoxLayout()
    button_layout.addWidget(self.start_button)
    button_layout.addWidget(self.clear_button)

    # 将组件添加到主布局
    main_layout.addWidget(self.text_edit)
    main_layout.addLayout(button_layout)

    # 应用布局到中央部件
    central_widget.setLayout(main_layout)

    # 连接按钮事件
    self.start_button.clicked.connect(self.on_start_task)
    self.clear_button.clicked.connect(self.on_clear)

def on_clear(self):
    # 清空文本框
    self.text_edit.clear()

def show_info(self, str_msg):
    # 在主线程中更新UI
    timestamp = time.strftime("%H:%M:%S", time.localtime())
    self.text_edit.append(f"[{timestamp}] {str_msg}")

def on_start_task(self):
    # 禁用按钮,避免重复点击
    self.start_button.setEnabled(False)
    self.start_button.setText("任务执行中...")

    # 清空之前的任务
    self.text_edit.clear()
    self.text_edit.append("开始执行串行任务...")

    # 添加5个任务到队列
    for i in range(5):
        task = Task(idx=i + 1)
        # 连接任务的日志信号
        task.logSignal.connect(self.show_info)
        self.task_manager.add_task(task)

    # 开始执行任务队列
    self.task_manager.start()

def on_all_tasks_finished(self):
    """所有任务完成后的回调"""
    self.start_button.setEnabled(True)
    self.start_button.setText("开始串行任务")
    self.show_info("所有任务已全部完成!")
if __name__ == '__main__':
	app = QApplication(sys.argv)
	window = MainWindow()
	window.show()
	sys.exit(app.exec_())``
posted @ 2026-01-09 00:40  QAQAQAQAQAQAQ  阅读(11)  评论(0)    收藏  举报