async 运行多线程时报错RuntimeError: There is no current event loop in thread ‘Thread-2(webui中也遇到)

原来使用:

loop = asyncio.get_event_loop()
task = asyncio.ensure_future(do_work(checker))
loop.run_until_complete(asyncio.wait([task]))
st = task.result()

添加了
new_loop = asyncio.new_event_loop()
    asyncio.set_event_loop(new_loop)

添加后如下:

new_loop = asyncio.new_event_loop()
    asyncio.set_event_loop(new_loop)
    loop = asyncio.get_event_loop()
    task = asyncio.ensure_future(do_work(checker))
    loop.run_until_complete(asyncio.wait([task]))
    st = task.result()

然后会报RuntimeError: There is no current event loop in thread 'Thread-2

根本原因在源码中:

def get_event_loop(self):
    """Get the event loop.
    This may be None or an instance of EventLoop.
    """
    if (self._local._loop is None and
            not self._local._set_called and
            isinstance(threading.current_thread(), threading._MainThread)):
        self.set_event_loop(self.new_event_loop())

    if self._local._loop is None:
        raise RuntimeError('There is no current event loop in thread %r.'
                            % threading.current_thread().name)

    return self._local._loop
 

在主线程中,调用get_event_loop总能返回属于主线程的event loop对象,如果是处于非主线程中,还需要调用set_event_loop方法指定一个event loop对象,这样get_event_loop才会获取到被标记的event loop对象:

def set_event_loop(self, loop):
    """Set the event loop."""
    self._local._set_called = True
    assert loop is None or isinstance(loop, AbstractEventLoop)
    self._local._loop = loop
 

官方文档:​ ​https://docs.python.org/3/library/asyncio-eventloop.html​​

我只截取上述用到的部分,具体详情请前往官方​ ​https://docs.python.org/3/library/asyncio-eventloop.html​​

参考:

https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues?q=There+is+no+current+event+loop+in+thread

https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/9441 

https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/9046