8.9. ThreadSafeFlag¶
asyncio.ThreadSafeFlag, Event sınıfının desteklemediği durum için asyncio’nun sağladığı sinyalleme ilkelidir: bir kesme işleyicisinin bir asyncio görevini uyandırması gerekir. Kesme, olay döngüsünün normal zamanlamasının dışında tetiklenir, dolayısıyla asyncio.Event.set() işleminin yaptığı kayıt tutma işlemi onun içinden güvenle yapılamaz.
8.9.1. Neden ayrı bir ilkel¶
asyncio.Event.set(), bekleyen coroutine’leri uyandıran kayıt tutma işlemini döngünün şu anda çalıştırdığı bir görevin içinden çağrıldığı varsayımıyla çalıştırır. Bir kesme işleyicisi bu varsayımı karşılamaz – herhangi iki komut arasında tetiklenebilir ve döngünün yarıladığı her ne işse onu bozabilir.
asyncio.ThreadSafeFlag.set(), bu bağlamlarda güvenli olacak şekilde yazılmıştır. Bu güvenliğin bedeli, Event sınıfından daha küçük bir özellik kümesidir: bir ThreadSafeFlag aynı anda yalnızca tek bir görev tarafından beklenebilir ve bekleyen görev uyandığında bayrak otomatik olarak sıfırlanır.
8.9.2. Temel yapı¶
Tipik bir kullanım, bir GPIO kesmesinin bir düğme basma olayını bir asyncio görevine devretmesidir:
import asyncio
from machine import Pin
flag = asyncio.ThreadSafeFlag()
def on_press(pin):
flag.set()
async def watcher():
button = Pin("P1", Pin.IN, Pin.PULL_UP)
button.irq(handler=on_press, trigger=Pin.IRQ_FALLING)
while True:
await flag.wait()
print("button pressed")
asyncio.run(watcher())
on_press, GPIO her tetiklendiğinde kesme bağlamında çalışır; yaptığı tek şey flag.set() çağırmaktır. Asyncio görevi watcher, bir döngü içinde flag.wait() üzerinde await yapar; bayrak her ayarlandığında görev devam eder, düğme basışının gerektirdiği işi çalıştırır, ardından tekrar beklemek üzere döngüye geri döner.
8.9.3. Üç yöntem¶
set()– bayrağı ayarlanmış olarak işaretler. Bir görev şu andawait()içinde bekliyorsa, onu devam etmek üzere zamanlar. Bir kesme işleyicisinden çağrılması güvenlidir.wait()– bir coroutine. Bayrak ayarlanana kadar bloklar, ardından döner. Bayrak dönüşte otomatik olarak temizlenir – bir sonrakiwaitçağrısı, bir sonrakiset()işlemine kadar yeniden bloklar.clear()– bayrağı beklemeden açıkça temizler. Görev hazır olmadan önce tetiklenmiş sahte erken birset()işlemini atmak için ilkwaitöncesinde kullanışlıdır.
8.9.4. Yalnızca tek bekleyen¶
Aynı anda yalnızca tek bir görev wait() içinde olabilir. Bir uygulamanın istediği yapı, bayrak için tek bir sahip görevdir – genellikle kesme işleyicisini kuran görevin aynısı – diğer görevler onunla Event, Lock veya bu ilkellerle korunan paylaşılan veri yapıları aracılığıyla iletişim kurar.
Bir düğmenin birkaç görevi uyandırması gerektiğinde, dağıtımın yapılacağı yer sahip görevdir: yukarıdaki watcher, her basıştan sonra some_event.set() çağırabilir ve some_event üzerinde bekleyen tüm görevler devam eder.