PyQt5编程:在QThread中使用asyncio

9 阅读1分钟

背景:在PyQt5开发中为防止后台代码运行阻塞窗口,会将耗时较长的代码定义在QThread中,而为了使代码更快的处理数据,会用到asyncio

asyncio的使用场景:在Python中,asyncio 库是用于编写单线程的并发代码的库,它使用异步I/O,这使得在执行I/O操作(如网络请求、文件操作等)时能够释放CPU,从而提高程序的效率和响应性。 asyncio的典型使用场景:网络编程、数据库操作、文件操作、定时任务和周期性任务、并发执行多个任务

下面的例子是网络编程场景

class TcpClientReceiveDataTag(QThread):
    Signal_ = pyqtSignal(str)

    def __init__(self,host_list,port):
        super(TcpClientReceiveDataTag, self).__init__()
        self.host_list = host_list
        self.port = port
        self.loop = asyncio.new_event_loop()

    def run(self):
        try:
            asyncio.set_event_loop(self.loop)
            self.loop.run_until_complete(self.main_task())
        except Exception as e:
            traceback.print_exc()
            log_exception()
            logger.info("tcp client:"+str(e))

    async def tcp_client_receive_data(self,host, port):
        try:
            reader, writer = await asyncio.open_connection(host, port)
            while True:
                try:
                    data = await reader.read(100)
                    if data:
                        hex_list = [f"{byte:02X}" for byte in data]
                        self.Signal_.emit(str(hex_list))
                except asyncio.CancelledError:
                    # 执行清理工作
                    break

            writer.close()
            await writer.wait_closed()

        except Exception as e:
            traceback.print_exc()
            
    async def main_task(self):
        # 启动所有连接任务
        tasks = [self.tcp_client_receive_data(host, self.port) for host in self.host_list]
        # 并发运行所有连接任务
        await asyncio.gather(*tasks)

    def stop(self):
        if self.loop.is_running():
            self.loop.call_soon_threadsafe(self.loop.stop)

线程启动:

self.Tcp_Client_Receive_Data_thread = TcpClientReceiveDataTag(["192.168.0.101"],8080)
self.Tcp_Client_Receive_Data_thread.Signal_.connect(self.receive_data_processing)
self.Tcp_Client_Receive_Data_thread.start()

线程停用:

self.Tcp_Client_Receive_Data_thread.stop()