首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >跨不同类的Python的asyncio.Event()

跨不同类的Python的asyncio.Event()
EN

Stack Overflow用户
提问于 2020-07-09 08:18:05
回答 1查看 4.9K关注 0票数 2

我正在编写一个Python程序来与基于CAN总线的设备进行交互。为此,我成功地使用了python模块。我还使用异步对异步事件作出反应。我编写了一个"CanBusManager“类,这个类由"CanBusSequencer”类使用。"CanBusManager“类负责生成/发送/接收消息,CanBusSequencer驱动要发送的消息序列。

在序列中的某个时刻,我希望等到接收到特定消息时“解锁”要在序列中发送的其余消息。代码概述:

main.py

代码语言:javascript
复制
async def main():
   
   event = asyncio.Event()
   sequencer = CanBusSequencer(event)
   task = asyncio.create_task(sequencer.doSequence())
   await task
 
asyncio.run(main(), debug=True)

canBusSequencer.py

代码语言:javascript
复制
from canBusManager import CanBusManager

class CanBusSequencer:
 
   def __init__(self, event)
 
      self.event = event
      self.canManager = CanBusManager(event)

   async def doSequence(self):
 
      for index, row in self.df_sequence.iterrows():
         if:...
            self.canManager.sendMsg(...)
         else:
            self.canManager.sendMsg(...)
            await self.event.wait()
            self.event.clear()

canBusManager.py

代码语言:javascript
复制
import can

class CanBusManager():
 
   def __init__(self, event):
 
      self.event = event
      self.startListening()
 
 **EDIT**
    def startListening(self):
    
       self.msgNotifier = can.Notifier(self.canBus, self.receivedMsgCallback)
 **EDIT**
 
   def receivedMsgCallback(self, msg):
 
      if(msg == ...):
         self.event.set()

现在,即使接收到相关消息并执行self.event.set(),我的程序仍然停留在等待self.event.set()的位置。使用debug = True运行程序会发现

代码语言:javascript
复制
RuntimeError: Non-thread-safe operation invoked on an event loop other than the current one

我不太明白。它与异步事件循环有关,在某种程度上没有正确定义/管理。我来自C++世界,目前正在用Python编写我的第一个大型程序。如能提供任何指导,将不胜感激:)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-09 08:39:56

您的问题无法解释如何安排调用receivedMsgCallback

如果使用后台线程的经典“异步”API调用它,那么它将从运行事件循环的线程外部调用。根据文献资料的说法,异步原语是而不是线程安全的,因此从另一个线程调用event.set()不能与正在运行的事件循环正确同步,这就是为什么您的程序应该在什么时候才会醒来的原因。

如果您希望从事件循环线程之外执行任何与异步相关的操作,例如调用Event.set,则需要使用call_soon_threadsafe或等效的。例如:

代码语言:javascript
复制
    def receivedMsgCallback(self, msg):
        if msg == ...:
            self.loop.call_soon_threadsafe(self.event.set)

事件循环对象应该提供给CanBusManager对象,也许可以将它传递给它的构造函数并将它分配给self.loop

另外,如果您创建一个任务只是为了立即等待它,那么首先您不需要任务。换句话说,您可以用更简单的task = asyncio.create_task(sequencer.doSequence()); await task代替await sequencer.doSequence()

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62810399

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档