python asyncio `loop.create_task` 在另一个线程的循环中添加任务,任务随机卡住

问题描述 投票:0回答:1

console's output

代码:

import asyncio
import time
from threading import Thread
import threading


loop = asyncio.new_event_loop()

def print_ids(s, l):
    print(f"{threading.current_thread().name}: self: {id(s)}")
    print(f"{threading.current_thread().name}: loop: {id(l)}")


class CorotineLoop:
    def __init__(self):
        # start thread
        self.thread1 = Thread(
            target=self.run_async1,
            daemon=True,
            name="one"
        )
        self.thread1.start()
        print_ids(self, loop)
        return

    def run_async1(self):
        # start loop
        print_ids(self, loop)
        asyncio.set_event_loop(loop)
        loop.run_forever()

    async def _run(self):
        # print stuff
        for i in range(2):
            print(threading.current_thread().name + ":", i)
            await asyncio.sleep(1)
        loop.close()

    def submit(self):
        # submit a task
        print("submitting...")
        loop.create_task(self._run())
        print("submitted")
        return



cloop = CorotineLoop()
cloop.submit()

print("start wating..")
while 1:
    time.sleep(0.2)

我正在做的是我想创建一个线程只是为了运行异步协程,主线程将运行其他正常同步任务

但随机地,它无缘无故地卡住,有时可以有时不行。

我可能写错了,所以有人可以帮我解决吗?

我尝试使用 vscode 运行调试来找出卡住的原因和位置,但无论我尝试了多少次,它都可以正常工作,这让我没有任何线索。

python async-await python-asyncio coroutine event-loop
1个回答
0
投票

您不能从循环运行所在的另一个线程调用“create_task”。

方法是使用

loop.call_soon_threadsafe()
https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.call_soon_threadsafe -

您的

submit
方法可以像这样修改,如果您希望
_run
成为协同例程,则需要在循环运行时在同一线程中运行包装同步函数来创建一个任务协同例程

    def submit(self):
        # submit a task
        print("submitting...")
        def _in_thread_callback():
            loop.create_task(self._run())
        loop.call_soon_threadsafe(_in_thread_callback)
        print("submitted")
        return

© www.soinside.com 2019 - 2024. All rights reserved.