comparison blender/asyncio_thread.py @ 2454:405abed9a45c

fix up asyncio-in-bg-thread sorcery
author drewp@bigasterisk.com
date Mon, 19 May 2025 21:25:32 -0700
parents b23afde50bc2
children
comparison
equal deleted inserted replaced
2453:b23afde50bc2 2454:405abed9a45c
1 import asyncio 1 import asyncio
2 from threading import Thread 2 import sys
3 from threading import Thread, get_ident
4 import time
3 from typing import Coroutine 5 from typing import Coroutine
4 6
5 7
8 def log(msg):
9 try:
10 rl = hex(id(asyncio.get_running_loop()))
11 except RuntimeError:
12 rl = '(no loop ----)'
13 sys.stderr.write(f"thread={hex(get_ident())} loop={rl} {msg}\n")
14
15
6 def startLoopInThread(task: Coroutine) -> asyncio.AbstractEventLoop: 16 def startLoopInThread(task: Coroutine) -> asyncio.AbstractEventLoop:
17 """
18 run a new event loop in a background thread. `task` is run in the new loop.
19 Caller should use this (from fg thread) to run further tasks:
20 asyncio.run_coroutine_threadsafe(task, returned_loop)
7 21
8 def start_background_loop(loop: asyncio.AbstractEventLoop) -> None: 22 """
9 asyncio.set_event_loop(loop) 23 log('🚋4 startLoopInThread enter ')
10 loop.run_forever() 24 loops = []
11 25
12 loop = asyncio.new_event_loop() 26 def start_background_loop() -> None:
13 t = Thread(target=start_background_loop, args=(loop,), daemon=True) 27
28 async def forever():
29 log('🚋6 log_loop')
30 loops.append(asyncio.get_running_loop())
31 while True:
32 await asyncio.sleep(100)
33
34 log('🚋5 make asyncio loop')
35 asyncio.run(forever())
36 log('🚋19 start_background_loop done')
37
38 t = Thread(target=start_background_loop, daemon=True)
14 t.start() 39 t.start()
40 while not loops:
41 time.sleep(.1)
42 loop = loops[0]
43 log('🚋7 loop has started in thread')
44
15 asyncio.run_coroutine_threadsafe(task, loop) 45 asyncio.run_coroutine_threadsafe(task, loop)
46 log('🚋8 started task')
47
48 log('🚋9 startLoopInThread exit')
16 return loop 49 return loop