多线程执行几秒后崩溃 [英] Crash after several seconds of execution with multithreading

查看:117
本文介绍了多线程执行几秒后崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基于这里这里在 PyQt5 中使用多线程迈出了我的第一步.启动程序后,出现图形用户界面,但几秒钟后崩溃并出现以下错误

Based on code from here and here I made my first steps with multithreading in PyQt5. After starting the program, the graphical user interface appears, but after several seconds it crashes with the following error

Process finished with exit code -1073740791 (0xC0000409)

谷歌搜索错误信息后,我相对确定多线程有问题.不幸的是,我不知道错误是什么以及如何修复.

After googling the error message, I am relatively sure that something is wrong with multithreading. Unfortunately I don't know what and how the error can be fixed.

代码

import sys
from datetime import datetime

import wmi

from PyQt5. QtCore import QObject, QRunnable, QThreadPool, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QApplication, QMainWindow, QTableWidget, QTableWidgetItem, QHeaderView


class KeyboardDetectorSignals(QObject):
    keyboard_changed = pyqtSignal(str)


class KeyboardDetector(QRunnable):

    def __init__(self):
        super().__init__()

        self.signals = KeyboardDetectorSignals()

    def run(self):

        device_connected_wql = "SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA \'Win32_Keyboard\'"
        device_disconnected_wql = "SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA \'Win32_Keyboard\'"

        c = wmi.WMI()
        connected_watcher = c.watch_for(raw_wql=device_connected_wql)
        disconnected_watcher = c.watch_for(raw_wql=device_disconnected_wql)

        while True:
            try:
                connected = connected_watcher(timeout_ms=10)
            except wmi.x_wmi_timed_out:
                pass
            else:
                if connected:
                    self.signals.keyboard_changed.emit("Keyboard connected.")

            try:
                disconnected = disconnected_watcher(timeout_ms=10)
            except wmi.x_wmi_timed_out:
                pass
            else:
                if disconnected:
                    self.signals.keyboard_changed.emit("Keyboard disconnected.")


class MainWindow(QMainWindow):

    def __init__(self):
        super().__init__()

        self.setGeometry(100, 100, 500, 500)
        self.setWindowTitle("Keyboard Logger")

        self.log_table = QTableWidget()
        self.log_table.setColumnCount(2)
        self.log_table.setShowGrid(True)
        self.log_table.setHorizontalHeaderLabels(["Time", "Event"])
        self.log_table.horizontalHeader().setStretchLastSection(True)
        self.log_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
        self.setCentralWidget(self.log_table)
        self.show()

        self.threadpool = QThreadPool()
        keyboard_detector = KeyboardDetector()
        keyboard_detector.signals.keyboard_changed.connect(self.add_row)
        self.threadpool.start(keyboard_detector)

    def add_row(self, event: str):
        now = datetime.now()
        datetime_string = now.strftime("%Y-%m-%d %H:%M:%S")

        row_count = self.log_table.rowCount()
        self.log_table.insertRow(row_count)
        self.log_table.setItem(row_count, 0, QTableWidgetItem(datetime_string))
        self.log_table.setItem(row_count, 1, QTableWidgetItem(event))


def main():
    app = QApplication(sys.argv)
    window = MainWindow()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()


更新 1: 删除了 @pyqtSlot().

从 CMD 运行脚本时出现以下错误:

Got the following error when running the script from the CMD:

Traceback (most recent call last):
  File "c:\users\ata\pycharmprojects\test\src\wmi\wmi.py", line 1340, in connect
    obj = GetObject(moniker)
  File "C:\Users\ata\AppData\Local\Programs\Python\Python37\lib\site-packages\win32com\client\__init__.py", line 72, in GetObject
    return Moniker(Pathname, clsctx)
  File "C:\Users\ata\AppData\Local\Programs\Python\Python37\lib\site-packages\win32com\client\__init__.py", line 87, in Moniker
    moniker, i, bindCtx = pythoncom.MkParseDisplayName(Pathname)
pywintypes.com_error: (-2147221020, 'Ung³ltige Syntax', None, None)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:\users\ata\pycharmprojects\test\src\wmi\wmi.py", line 1354, in connect
    handle_com_error()
  File "c:\users\ata\pycharmprojects\test\src\wmi\wmi.py", line 258, in handle_com_error
    raise klass(com_error=err)
wmi.x_wmi_uninitialised_thread: <x_wmi: Unexpected COM Error (-2147221020, 'Ung³ltige Syntax', None, None)>

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "main.py", line 26, in run
    c = wmi.WMI()
  File "c:\users\ata\pycharmprojects\test\src\wmi\wmi.py", line 1357, in connect
    raise x_wmi_uninitialised_thread("WMI returned a syntax error: you're probably running inside a thread without first calling pythoncom.CoInitialize[Ex]")
wmi.x_wmi_uninitialised_thread: <x_wmi: WMI returned a syntax error: you're probably running inside a thread without first calling pythoncom.CoInitialize[Ex] (no underlying exception)>
PS C:\Users\ata\PycharmProjects\Snippets\KeyboardLogger>

推荐答案

PyQt 是线程安全的,与 Qt 是线程安全的一样.Qt 文档 会告诉您他们 API 的哪些部分可以保证如此,以及在什么情况下.

PyQt is thread-safe to the same extent that Qt is thread-safe. The Qt docs will tell you which parts of their API are guaranteed to be so, and under what circumstances.

跨线程信号线程安全的.

一种线程安全的编写方式是使用 mutex

A thread-safe way of writing this would be to use a mutex

这篇关于多线程执行几秒后崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆