在单独的线程中运行异步循环,信号来自和循环

2024-02-12

我正在尝试制作一个在后台与多个 BLE 设备进行通信的 UI。 为此,我实现了一个运行 asyncio.loop 的单独线程。这是必要的,因为我使用 bleak 0.9.1 连接到设备。

使用信号和槽将数据从 UI 线程获取到工作线程效果很好。然而,它在另一个方向上不起作用。据我所知,这是因为线程正忙于运行循环并且永远不会停止这样做。因此,它无法处理来自 UI 线程的输入。

下面有一个示例代码显示了问题。

有没有办法在运行 asyncio 循环时处理线程中的输入槽?

import sys
from PyQt5.QtWidgets import QWidget, QPushButton, QApplication, QVBoxLayout
from PyQt5.QtCore import QThread, QObject, pyqtSignal, pyqtSlot
import asyncio

class Test_Thread(QObject):
    signal_back = pyqtSignal(int)

    def __init__(self,
                 loop: asyncio.AbstractEventLoop,
                 parent=None):
        super(Test_Thread, self).__init__(parent)
        self.text = "Task1 not configured"
        self.loop = loop
        self.counter = 0

    @pyqtSlot(str)
    def set_text_slot(self, txt):
        self.text = txt

    async def do_stuff1(self):
        while True:
            print(self.text)
            await asyncio.sleep(2.0)

    async def do_stuff2(self):
        while True:
            self.counter += 1
            self.signal_back.emit(self.counter)
            await asyncio.sleep(1.0)

    def work(self):
        #run the event loop
        try:
            asyncio.ensure_future(self.do_stuff1(), loop=self.loop)
            asyncio.ensure_future(self.do_stuff2(), loop=self.loop)
            self.loop.run_forever()
        finally:
            print("Disconnect...")


class Window(QWidget):

    set_text_signal = pyqtSignal(str)

    def __init__(self, parent=None):
        super(Window, self).__init__()
        self.initUi()
        self.startThread()

    def initUi(self):
        layout = QVBoxLayout()
        self.button = QPushButton('User input')
        self.button.clicked.connect(self.sendtotask)
        layout.addWidget(self.button)
        self.setLayout(layout)
        self.show()

    def startThread(self):
        loop = asyncio.get_event_loop()
        self.asyciothread = Test_Thread(loop)
        self.thread = QThread()
        self.asyciothread.moveToThread(self.thread)

        self.set_text_signal.connect(self.asyciothread.set_text_slot)
        self.asyciothread.signal_back.connect(self.receivefromthread)
        self.thread.started.connect(self.asyciothread.work)

        self.thread.start()

    @pyqtSlot(int)
    def receivefromthread(self, number):
        print(str(number))

    def sendtotask(self):
        self.set_text_signal.emit("Task: Configured")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    ui = Window()
    ui.show()
    sys.exit(app.exec_())

没有必要使用线程来使用 Qt 的 asyncio,因为有像这样的库asyncqt https://github.com/gmarull/asyncqt and qasync https://github.com/CabbageDevelopment/qasync启用它:

import asyncio
import sys

from PyQt5.QtWidgets import QWidget, QPushButton, QApplication, QVBoxLayout
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot

from asyncqt import QEventLoop
# from qasync import QEventLoop


class Worker(QObject):
    signal_back = pyqtSignal(int)

    def __init__(self, loop: asyncio.AbstractEventLoop, parent=None):
        super(Worker, self).__init__(parent)
        self.text = "Task1 not configured"
        self.loop = loop
        self.counter = 0

    @pyqtSlot(str)
    def set_text_slot(self, txt):
        self.text = txt

    async def do_stuff1(self):
        while True:
            print(self.text)
            await asyncio.sleep(2.0)

    async def do_stuff2(self):
        while True:
            self.counter += 1
            self.signal_back.emit(self.counter)
            await asyncio.sleep(1.0)

    def work(self):
        asyncio.ensure_future(self.do_stuff1(), loop=self.loop)
        asyncio.ensure_future(self.do_stuff2(), loop=self.loop)


class Window(QWidget):
    set_text_signal = pyqtSignal(str)

    def __init__(self, parent=None):
        super(Window, self).__init__()
        self.initUi()
        self.start_task()

    def initUi(self):
        layout = QVBoxLayout(self)
        self.button = QPushButton("User input")
        self.button.clicked.connect(self.sendtotask)
        layout.addWidget(self.button)

    def start_task(self):
        loop = asyncio.get_event_loop()
        self.worker = Worker(loop)
        self.set_text_signal.connect(self.worker.set_text_slot)
        self.worker.signal_back.connect(self.receive_from_worker)
        self.worker.work()

    @pyqtSlot(int)
    def receive_from_worker(self, number):
        print(str(number))

    def sendtotask(self):
        self.set_text_signal.emit("Task: Configured")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    loop = QEventLoop(app)
    asyncio.set_event_loop(loop)
    ui = Window()
    ui.show()
    with loop:
        loop.run_forever()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在单独的线程中运行异步循环,信号来自和循环 的相关文章

  • 区分大小写的实体识别

    我的关键字全部以小写形式存储 例如 折扣耐克鞋 我正在尝试对其执行实体提取 我遇到的问题是 spaCy 在 NER 方面似乎区分大小写 请注意 我不认为这是 spaCy 特有的 当我跑步时 doc nlp u i love nike sho
  • 高效地将大型 Pandas 数据帧写入磁盘

    我正在尝试找到使用 Python Pandas 高效地将大型数据帧 250MB 写入磁盘或从磁盘写入的最佳方法 我已经尝试了所有方法Python 数据分析 但表现却非常令人失望 这是一个更大项目的一部分 该项目探索将我们当前的分析 数据管理
  • minAreaRect OpenCV 返回的裁剪矩形 [Python]

    minAreaRectOpenCV 中返回一个旋转的矩形 如何裁剪矩形内图像的这部分 boxPoints返回旋转矩形的角点的坐标 以便可以通过循环框内的点来访问像素 但是在 Python 中是否有更快的裁剪方法 EDIT See code在
  • sy.sympify(str(表达式)) 不等于表达式

    据我了解 str将 SymPy 表达式转换为字符串并sympify将字符串转换为 SymPy 表达式 因此 我希望以下内容成立 对于合理的表达 gt gt gt sy sympify str expr expr True 我尝试过这个 确实
  • 检查子字符串是否在字符串列表中?

    我之前已经找到了这个问题的一些答案 但它们对于当前的Python版本来说似乎已经过时了 或者至少它们对我不起作用 我想检查字符串列表中是否包含子字符串 我只需要布尔结果 我找到了这个解决方案 word to check or wordlis
  • 在 PhotoImage 下调整图像大小

    我需要调整图像大小 但我想避免使用 PIL 因为我无法使其在 OS X 下工作 不要问我为什么 无论如何 因为我对 gif pgm ppm 感到满意 所以 PhotoImage 类对我来说没问题 photoImg PhotoImage fi
  • 如何将 numpy rearray 的子集转换为连续数组?

    我有一个recarray来自读取 csv 文件 我有兴趣将列的子集转换为连续浮点数组 我想避免将它们转换为列表或将它们一一堆叠 我尝试了中的建议https stackoverflow com a 11792956 https stackov
  • 如何调试 numpy 掩码

    这个问题与this one https stackoverflow com q 73672739 11004423 我有一个正在尝试矢量化的函数 这是原来的函数 def aspect good angle float planet1 goo
  • 当我从本地计算机更改为虚拟主机时,从 python 脚本调用 pdftotext 不起作用

    我编写了一个小的 python 脚本来解析 提取 PDF 中的信息 我在本地机器上测试了它 我有 python 2 6 2 和 pdftotext 版本 0 12 4 我正在尝试在我的虚拟主机服务器 dreamhost 上运行它 它有 py
  • 将多索引转换为行式多维 NumPy 数组。

    假设我有一个类似于以下示例的 MultiIndex DataFrame多索引文档 http pandas pydata org pandas docs stable advanced html gt gt gt df 0 1 2 3 fir
  • 获取 int() 参数必须是字符串或数字,而不是“Column”- Apache Spark

    如果我使用以下代码 我会收到此异常 int argument must be a string or a number not Column df df withColumn FY F when df ID substr 5 2 isin
  • 如何仅注释堆积条形图的一个类别

    我有一个数据框示例 如下所示 data Date 2021 07 18 2021 07 19 2021 07 20 2021 07 21 2021 07 22 2021 07 23 Invalid NaN 1 1 NaN NaN NaN N
  • 为什么在读取字典时要锁定

    我对我正在阅读的一本关于线程的书 C 3 in a Nutshell 中的代码列表感到困惑 在 应用程序服务器中的线程安全 主题中 给出了以下代码作为 UserCache 的示例 static class UserCache static
  • django 中的身份验证方法返回 None

    你好 我在 django 中做了一个简单的注册和登录页面 当想要登录时 登录视图中的身份验证方法不返回任何内容 我的身份验证应用程序 模型 py from django db import models from django contri
  • 导入目录下的所有模块

    有没有办法导入当前目录中的所有模块 并返回它们的列表 例如 对于包含以下内容的目录 mod py mod2 py mod3 py 它会给你
  • 错误:尝试使用 scrappy 登录时出现 raise ValueError("No element found in %s" % response)

    问题描述 我想从我大学的bbs上抓取一些信息 这是地址 http bbs byr cn http bbs byr cn下面是我的蜘蛛的代码 from lxml import etree import scrapy try from scra
  • Python 或 C 语言中的 Matlab / Octave bwdist()

    有谁知道 Matlab Octave bwdist 函数的 Python 替代品 此函数返回给定矩阵的每个单元格到最近的非零单元格的欧几里得距离 我看到了一个 Octave C 实现 一个纯 Matlab 实现 我想知道是否有人必须用 AN
  • 更改用作函数全局作用域的字典

    我想做一个 purePython 的装饰器 其中一部分是能够有选择地禁止访问函数的全局范围 有没有一种方法可以以编程方式更改哪个字典事物充当函数的全局 外部作用域 因此 例如在下面我希望能够拦截对f in h并抛出错误 但我想允许访问g因为
  • 在 python 中使用高精度时间戳

    嘿 我正在使用 python 处理日期时间 我想知道解析这个时间戳的最佳方法是什么 时间戳是ISO标准 这里是一个例子 2010 06 19T08 17 14 078685237Z 现在到目前为止我已经使用过 time datetime d
  • python 日志记录替代方案 [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 蟒蛇记录模块 http docs python org library logging html使用起来

随机推荐