簡體   English   中英

python asyncio.Event.wait()不響應event.set()

[英]python asyncio.Event.wait() not responding to event.set()

計划是使多個IO例程“同時”運行(特別是在Raspberry Pi上,操作IO引腳並同時運行SPI接口)。 我嘗試使用asyncio來實現這一目標。 但是,我的簡單試用無法運行。
這是該代碼的簡化版本,省略了IO引腳的詳細信息:

"""\
Reduced problem representation:
this won't run because GPIO details have been left out
"""

import RPi.GPIO as gpio
import asyncio

GPIO_PB = 12         # Define pushbutton channel

async def payload():
    """ Provides some payload sequence using asyncio.sleep() """
    #Payload action
    await asyncio.sleep(1)
    #Payload action
    await asyncio.sleep(1)

class IOEvent(asyncio.locks.Event):
    """\
    Create an Event for asyncio, fired by a callback from GPIO
    The callback must take a single parameter: a gpio channel number
    """
    def __init__(self, ioChannel, loop):
        super().__init__(loop = loop)
        self.io = ioChannel

    def get_callback(self):
        "The callback is a closure that knows self when called"
        def callback( ch ):
            print("callback for channel {}".format(ch))
            if ch == self.io and not self.is_set():
                print(repr(self))
                self.set()
                print(repr(self))
        return callback

async def Worker(loop, event):
    print("Entering Worker: {}".format(repr(loop)))
    while loop.is_running():
        print("Worker waiting for {}".format(repr(event)))
        await event.wait()
        print("Worker has event")
        event.clear()
        await payload()
        print("payload ended")

loop = asyncio.get_event_loop()

# Create an event for the button
pb_event = IOEvent( GPIO_PB, loop)

# register the pushbutton's callback
# Pushing the button calls this callback function
gpio.add_event_callback( GPIO_PB, pb_event.get_callback() )

try:
    asyncio.ensure_future(Worker(loop, pb_event))
    loop.run_forever()
except KeyboardInterrupt:
    pass
finally:
    print("Closing Loop")
    loop.stop()
    loop.close()

我得到的輸出是這樣的:

Entering Worker: <_UnixSelectorEventLoop running=True closed=False debug=False>
Worker waiting for <__main__.IOEvent object at 0x76a2a950 [unset]>
callback for channel 12
<__main__.IOEvent object at 0x76a2a950 [unset,waiters:1]>
<__main__.IOEvent object at 0x76a2a950 [set,waiters:1]>
callback for channel 12

這些行重復顯示按鈕並正確觸發其回調例程。 首次調用set()函數。 用於wait()調用和set()調用的事件是相同的。 但是,在await event.wait()調用之后,永遠不會出現消息“ Worker has event”

我看了看PyQt5和asyncio:yield from never finishs ,但是除了默認循環,我看不到其他任何循環。

為什么wait()永不返回? 我怎么知道?

add_event_callback設置的add_event_callback必須從不同的線程調用,因為它們是自動調用的。 這意味着您不能在asyncio.Event上調用set在它們之間進行同步,因為默認情況下asyncio類不是線程安全的。

要從其他線程喚醒asyncio.Event ,可以將event.set傳遞給loop.call_soon_threadsafe 對於您的情況,您將更改:

self.set()

至:

self._loop.call_soon_threadsafe(self.set)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM