• pyqt 多线程出现问题


    1. import time
    2. from PyQt5.Qt import *
    3. class WorkThread(QThread):
    4. finished=pyqtSignal()
    5. def __init__(self):
    6. super(WorkThread, self).__init__()
    7. self.is_running = None
    8. def run(self):
    9. print('running')
    10. self.is_running = True
    11. while self.is_running:
    12. print('working....')
    13. time.sleep(1)
    14. self.finished.emit()
    15. def stop(self):
    16. self.is_running = False
    17. class MainWindow(QMainWindow):
    18. def __init__(self):
    19. super(MainWindow, self).__init__()
    20. self.resize(600,500)
    21. self.work = WorkThread()
    22. self.work.setParent(self)
    23. self.work.destroyed.connect(lambda :print('thread is destoryed'))
    24. self.btn = QPushButton("start")
    25. self.btn2 = QPushButton("stop")
    26. layout = QVBoxLayout()
    27. layout.addWidget(self.btn)
    28. layout.addWidget(self.btn2)
    29. central_widget = QWidget()
    30. central_widget.setLayout(layout)
    31. self.setCentralWidget(central_widget)
    32. #slots
    33. self.btn.clicked.connect(self.start_thread)
    34. self.btn2.clicked.connect(self.stop_thread)
    35. def start_thread(self):
    36. self.work.start()
    37. def stop_thread(self):
    38. self.work.stop()
    39. def closeEvent(self, event) -> None:
    40. self.work.stop()

    在运行时关闭窗口时会出错的原因是,当关闭窗口时,工作线程仍然在运行,并且在调用`self.work.stop()`时,工作线程已经被销毁,但是在`stop()`方法中仍然尝试设置`self.is_running`为False,这会导致AttributeError。

    为了解决这个问题,你可以在关闭窗口时先停止工作线程,然后再关闭窗口。你可以在`closeEvent`方法中添加一个判断,如果工作线程正在运行,则先停止工作线程,然后再关闭窗口。代码如下:

    ```python
    def closeEvent(self, event):
        if self.work.isRunning():
            self.work.stop()
            self.work.wait()  # 等待工作线程结束
        event.accept()
    ```

    这样,当关闭窗口时,会先停止工作线程并等待其结束,然后再关闭窗口,避免了出错的情况。

    正确代码如下:

    1. import time
    2. from PyQt5.Qt import *
    3. class WorkThread(QThread):
    4. def __init__(self):
    5. super(WorkThread, self).__init__()
    6. self.is_running = None
    7. def run(self):
    8. print('running')
    9. self.is_running = True
    10. while self.is_running:
    11. print('working....')
    12. time.sleep(1)
    13. def stop(self):
    14. self.is_running = False
    15. class MainWindow(QMainWindow):
    16. def __init__(self):
    17. super(MainWindow, self).__init__()
    18. self.resize(600,500)
    19. self.work = WorkThread()
    20. self.work.setParent(self)
    21. self.work.destroyed.connect(lambda :print('thread is destoryed'))
    22. self.btn = QPushButton("start")
    23. self.btn2 = QPushButton("stop")
    24. layout = QVBoxLayout()
    25. layout.addWidget(self.btn)
    26. layout.addWidget(self.btn2)
    27. central_widget = QWidget()
    28. central_widget.setLayout(layout)
    29. self.setCentralWidget(central_widget)
    30. #slots
    31. self.btn.clicked.connect(self.start_thread)
    32. self.btn2.clicked.connect(self.stop_thread)
    33. def start_thread(self):
    34. self.work.start()
    35. def stop_thread(self):
    36. self.work.stop()
    37. def closeEvent(self, event) -> None:
    38. if self.work.isRunning():
    39. self.work.stop()
    40. self.work.wait()
    41. event.accept()
    1. import time
    2. from PyQt5.Qt import *
    3. import time
    4. qum_1 = QMutex()
    5. class Thread_1(QThread):
    6. def __init__(self):
    7. super(Thread_1, self).__init__()
    8. def run(self):
    9. qum_1.lock()
    10. values=[1,2,3,4,5]
    11. for i in values:
    12. print(i)
    13. time.sleep(0.5)
    14. qum_1.unlock()
    15. class Thread_2(QThread):
    16. _signal = pyqtSignal()
    17. def __init__(self):
    18. super(Thread_2, self).__init__()
    19. def run(self):
    20. values = ["a","b","c","d","e"]
    21. for i in values:
    22. print(i)
    23. time.sleep(1)
    24. self._signal.emit()
    25. class Window(QWidget):
    26. def __init__(self):
    27. super().__init__()
    28. self.setWindowTitle("的学习")
    29. self.resize(500,500)
    30. self.setup_ui()
    31. self.t=Thread_1()
    32. self.t2=Thread_2()
    33. self.t2._signal.connect(lambda :self.btn2.setEnabled(True))
    34. def setup_ui(self):
    35. self.btn = QPushButton('btn1',self)
    36. self.btn.move(10,20)
    37. self.btn.clicked.connect(self.btn_click)
    38. self.btn2 = QPushButton('btn2',self)
    39. self.btn.move(10,80)
    40. self.btn2.clicked.connect(self.btn2_click)
    41. def btn_click(self):
    42. self.t.start()
    43. def btn2_click(self):
    44. self.btn2.setEnabled(False)
    45. self.t2.start()
    46. if __name__ == '__main__':
    47. import sys
    48. app=QApplication(sys.argv)
    49. win=Window()
    50. win.show()
    51. sys.exit(app.exec_())
    1. import threading
    2. import time
    3. class Task(threading.Thread):
    4. def __init__(self):
    5. super(Task, self).__init__()
    6. self._stop_event = threading.Event()
    7. def run(self):
    8. while not self._stop_event.is_set():
    9. print('hello')
    10. def stop(self):
    11. self._stop_event.set()
    12. t=Task()
    13. t.start()
    14. time.sleep(5)
    15. t.stop()

  • 相关阅读:
    使用SystemParametersInfo访问用户界面设置
    【个人博客搭建】(24)统一api接口返回格式
    SpringMVC简单介绍与使用
    Steam项目推进 (一) ——项目情况简述
    在 CentOS 8.2 上安装 MySQL C/C++ 客户端库 libmysqlclient.so
    excel怎么设置密码?加密文件这么做!
    Dephi2007以任意字符串分隔字符
    MySQL Varchar前缀索引的一个细节
    大数据技术基础实验十五:Storm实验——实时WordCountTopology
    MYSQL常用命令
  • 原文地址:https://blog.csdn.net/weixin_49577420/article/details/132901982