@@ -1067,14 +1067,59 @@ Scheduling From Other Threads
1067
1067
This function is meant to be called from a different OS thread
1068
1068
than the one where the event loop is running. Example::
1069
1069
1070
- # Create a coroutine
1071
- coro = asyncio.sleep(1, result=3)
1072
-
1073
- # Submit the coroutine to a given loop
1074
- future = asyncio.run_coroutine_threadsafe(coro, loop)
1075
-
1076
- # Wait for the result with an optional timeout argument
1077
- assert future.result(timeout) == 3
1070
+ def in_thread(loop: asyncio.AbstractEventLoop) -> None:
1071
+ # Run some blocking IO
1072
+ pathlib.Path("example.txt").write_text("hello world", encoding="utf8")
1073
+
1074
+ # Create a coroutine
1075
+ coro = asyncio.sleep(1, result=3)
1076
+
1077
+ # Submit the coroutine to a given loop
1078
+ future = asyncio.run_coroutine_threadsafe(coro, loop)
1079
+
1080
+ # Wait for the result with an optional timeout argument
1081
+ assert future.result(timeout=2) == 3
1082
+
1083
+ async def amain() -> None:
1084
+ # Get the running loop
1085
+ loop = asyncio.get_running_loop()
1086
+
1087
+ # Run something in a thread
1088
+ await asyncio.to_thread(in_thread, loop)
1089
+
1090
+ It's also possible to run the other way around. Example::
1091
+
1092
+ @contextlib.contextmanager
1093
+ def loop_in_thread() -> Generator[asyncio.AbstractEventLoop]:
1094
+ loop_fut = concurrent.futures.Future[asyncio.AbstractEventLoop]()
1095
+ stop_event = asyncio.Event()
1096
+
1097
+ async def main() -> None:
1098
+ loop_fut.set_result(asyncio.get_running_loop())
1099
+ await stop_event.wait()
1100
+
1101
+ with concurrent.futures.ThreadPoolExecutor(1) as tpe:
1102
+ complete_fut = tpe.submit(asyncio.run, main())
1103
+ for fut in concurrent.futures.as_completed((loop_fut, complete_fut)):
1104
+ if fut is loop_fut:
1105
+ loop = loop_fut.result()
1106
+ try:
1107
+ yield loop
1108
+ finally:
1109
+ loop.call_soon_threadsafe(stop_event.set)
1110
+ else:
1111
+ fut.result()
1112
+
1113
+ # Create a loop in another thread
1114
+ with loop_in_thread() as loop:
1115
+ # Create a coroutine
1116
+ coro = asyncio.sleep(1, result=3)
1117
+
1118
+ # Submit the coroutine to a given loop
1119
+ future = asyncio.run_coroutine_threadsafe(coro, loop)
1120
+
1121
+ # Wait for the result with an optional timeout argument
1122
+ assert future.result(timeout=2) == 3
1078
1123
1079
1124
If an exception is raised in the coroutine, the returned Future
1080
1125
will be notified. It can also be used to cancel the task in
0 commit comments