8.7. Događaji¶
asyncio.Event je najjednostavniji primitiv za signalizaciju koji modul pruža. Jedna korutina postavlja događaj kada se nešto dogodilo; bilo koji broj drugih korutina čeka da se događaj postavi prije nastavka. Nema korisnog tereta – događaj je booleova vrijednost koja se uključi i ostaje uključena dok je nešto ne obriše.
8.7.1. Osnovni oblik¶
import asyncio
async def waiter(evt):
print("waiting")
await evt.wait()
print("got signal")
async def main():
evt = asyncio.Event()
asyncio.create_task(waiter(evt))
await asyncio.sleep(1)
evt.set()
await asyncio.sleep(0)
asyncio.run(main())
Zadatak koji čeka se izvodi, dolazi do await evt.wait() i obustavlja se – događaj počinje u obrisanom stanju, pa poziv wait prepušta kontrolu natrag petlji. Sekundu kasnije main poziva evt.set() i zadatak koji čeka raspoređuje se za nastavak. Završni await asyncio.sleep(0) je samo prepuštanje kontrole kako bi petlja dobila priliku izvesti zadatak koji čeka prije nego što se main vrati.
8.7.2. Četiri metode¶
set()– prebacuje događaj u postavljeno stanje i raspoređuje za nastavak svaku korutinu trenutno blokiranu nawait(). Događaj ostaje postavljen dok se ne obriše.clear()– prebacuje događaj natrag u obrisano stanje. Korutine koje nakon togaawait wait()ponovno će se blokirati.wait()– korutina. Ako je događaj već postavljen, vraća se odmah. Inače se blokira dok ga nešto ne postavi.is_set()– vraća trenutno stanje bez blokiranja. Korisno kada korutina želi provjeriti događaj bez čekanja na njega.
8.7.3. Više čekatelja¶
Nekoliko korutina može awaitati isti događaj. Kada nešto pozove set() sve se raspoređuju za nastavak. Događaj je prema zadanim postavkama jedan-prema-više; nema potrebe za više događaja koji se granaju prema više čekatelja.
8.7.4. Ponovna upotreba događaja¶
Uobičajeni obrazac je upotreba događaja iznova i iznova – korutina koja se izvodi jednom po signalu – brisanjem nakon svakog prolaza:
async def worker(go):
while True:
await go.wait()
do_one_unit_of_work()
go.clear()
Proizvođač postavlja događaj kad god ima posla; radnik ga briše čim je preuzeo signal. Ako proizvođač možda ponovno postavi događaj prije nego što se radnik probudio, radnik bi mogao htjeti obraditi taj slučaj (while go.is_set(): ...) prije brisanja.
8.7.5. Sigurni konteksti¶
Event nije sigurno pozvati set() iznutra rukovatelja prekidom. Mehanizam koji koristi za raspoređivanje čekatelja pretpostavlja da se izvodi unutar vlastitog konteksta petlje događaja, što prekidi nisu. Za buđenje asyncio zadatka iz rukovatelja prekidom, ThreadSafeFlag (uskoro obrađen) je pravi primitiv.