asyncio:等待其他线程的事件 [英] asyncio: Wait for event from other thread

查看:103
本文介绍了asyncio:等待其他线程的事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用Python设计一个应用程序,该应用程序应该访问机器以执行一些(冗长的)任务.对于与网络相关的所有事情,asyncio模块似乎都是一个不错的选择,但是现在我需要访问一个特定组件的串行端口.我已经为实际的串行端口实现了某种抽象层,但无法弄清楚如何将其合理地与asyncio集成.

I'm designing an application in Python which should access a machine to perform some (lengthy) tasks. The asyncio module seems to be a good choice for everything that is network-related, but now I need to access the serial port for one specific component. I've implemented kind of an abstraction layer for the actual serial port stuff, but can't figure out how to sensibly integrate this with asyncio.

以下设置:我有一个线程运行一个循环,该循环定期与机器对话并解码响应.使用方法enqueue_query(),我可以将查询字符串放入队列,然后由另一个线程发送到机器并引起响应.通过传入threading.Event(或带有set()方法的任何内容),调用方可以执行阻塞等待响应.然后看起来像这样:

Following setup: I have a thread running a loop, which regularly talks to the machine and decodes the responses. Using a method enqueue_query(), I can put a query string into a queue, which will then be sent to the machine by the other thread and cause a response. By passing in a threading.Event (or anything with a set() method), the caller can perform a blocking wait for the response. This can then look something like this:

f = threading.Event()
ch.enqueue_query('2 getnlimit', f)
f.wait()
print(ch.get_query_responses())

我现在的目标是将这些行放入协程中,并让asyncio处理此等待,以便应用程序同时可以执行其他操作.我该怎么办?可以通过将f.wait()包装到Executor中来工作,但这似乎有点愚蠢,因为这会创建一个新线程,只是为了等待另一个线程做某事.

My goal is now to put those lines into a coroutine and have asyncio handle this waiting, so that the application can do something else in the meantime. How could I do this? It would probably work by wrapping the f.wait() into an Executor, but this seems to be a bit stupid, as this would create a new thread only to wait for another thread to do something.

谢谢! 最好的祝福, 菲利普(Philipp)

Thanks! Best regards, Philipp

推荐答案

通过传入threading.Event(或带有set()方法的任何内容),调用方可以执行阻塞等待响应.

By passing in a threading.Event (or anything with a set() method), the caller can perform a blocking wait for the response.

鉴于查询功能的上述行为,您所需要的只是asyncio.Event的线程安全版本.只需三行代码:

Given the above behavior of your query function, all you need is a thread-safe version of asyncio.Event. It's just 3 lines of code:

import asyncio
class Event_ts(asyncio.Event):
    #TODO: clear() method
    def set(self):
        #FIXME: The _loop attribute is not documented as public api!
        self._loop.call_soon_threadsafe(super().set)

功能测试:

def threaded(event):
    import time
    while True:
        event.set()
        time.sleep(1)

async def main():
    import threading
    e = Event_ts()
    threading.Thread(target=threaded, args=(e,)).start()
    while True:
        await e.wait()
        e.clear()
        print('whatever')

asyncio.ensure_future(main())
asyncio.get_event_loop().run_forever()

这篇关于asyncio:等待其他线程的事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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