diff 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
line wrap: on
line diff
--- a/blender/asyncio_thread.py	Sun May 18 20:08:35 2025 -0700
+++ b/blender/asyncio_thread.py	Mon May 19 21:25:32 2025 -0700
@@ -1,16 +1,49 @@
 import asyncio
-from threading import Thread
+import sys
+from threading import Thread, get_ident
+import time
 from typing import Coroutine
 
 
+def log(msg):
+    try:
+        rl = hex(id(asyncio.get_running_loop()))
+    except RuntimeError:
+        rl = '(no loop ----)'
+    sys.stderr.write(f"thread={hex(get_ident())} loop={rl} {msg}\n")
+
+
 def startLoopInThread(task: Coroutine) -> asyncio.AbstractEventLoop:
+    """
+    run a new event loop in a background thread. `task` is run in the new loop.
+    Caller should use this (from fg thread) to run further tasks:
+      asyncio.run_coroutine_threadsafe(task, returned_loop)
 
-    def start_background_loop(loop: asyncio.AbstractEventLoop) -> None:
-        asyncio.set_event_loop(loop)
-        loop.run_forever()
+    """
+    log('🚋4 startLoopInThread enter ')
+    loops = []
+
+    def start_background_loop() -> None:
+
+        async def forever():
+            log('🚋6 log_loop')
+            loops.append(asyncio.get_running_loop())
+            while True:
+                await asyncio.sleep(100)
 
-    loop = asyncio.new_event_loop()
-    t = Thread(target=start_background_loop, args=(loop,), daemon=True)
+        log('🚋5 make asyncio loop')
+        asyncio.run(forever())
+        log('🚋19 start_background_loop done')
+
+    t = Thread(target=start_background_loop, daemon=True)
     t.start()
+    while not loops:
+        time.sleep(.1)
+    loop = loops[0]
+    log('🚋7 loop has started in thread')
+
     asyncio.run_coroutine_threadsafe(task, loop)
+    log('🚋8 started task')
+
+    log('🚋9 startLoopInThread exit')
     return loop