线程和 asyncio:任务已销毁,但处于挂起状态
Posted
技术标签:
【中文标题】线程和 asyncio:任务已销毁,但处于挂起状态【英文标题】:Thread and asyncio: Task was destroyed but it is pending 【发布时间】:2017-11-27 15:09:16 【问题描述】:我有一个运行异步循环的线程。我开始了一个未来的任务,做与这里无关的事情。当我停止线程时,我也停止了 asyncio 循环。但是,我似乎无法取消池任务并获得Task was destroyed but it is pending!
这是一个玩具示例:
from contextlib import suppress
from threading import Thread
from time import sleep
import asyncio
class Hardware(Thread):
def __init__(self, *args, **kwargs):
super(Hardware, self).__init__(*args, **kwargs)
self.loop = None
self._poll_task = None
def run(self):
self.loop = asyncio.new_event_loop()
asyncio.set_event_loop(self.loop)
self.loop.create_task(self._poll())
self.loop.run_forever()
async def _poll(self):
print('ook')
await asyncio.sleep(1.0)
self._poll_task = asyncio.ensure_future(self._poll())
return self._poll_task
def stop(self):
if self._poll_task is not None:
self.loop.call_soon_threadsafe(self._poll_task.cancel)
with suppress(asyncio.CancelledError):
self.loop.call_soon_threadsafe(self.loop.stop)
hw = Hardware()
try:
hw.start()
while True:
sleep(.1)
except KeyboardInterrupt:
hw.stop()
hw.join()
运行它输出:
; python ook.py
ook
ook
^CTask was destroyed but it is pending!
task: <Task pending coro=<Hardware._poll() running at ook.py:22> wait_for=<Future cancelled>>
我做错了什么?
【问题讨论】:
我对代码进行了一些重构,以便更好地启动/关闭。 【参考方案1】:你不仅应该在任务上调用cancel()
,还应该调用await its cancellation,而不是像你一样只是停止循环。
from contextlib import suppress
from threading import Thread
from time import sleep
import asyncio
class Hardware(Thread):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.loop = None
self._poll_task = None
def run(self):
self.loop = asyncio.new_event_loop()
loop = self.loop
asyncio.set_event_loop(loop)
try:
# create task:
self._poll_task = asyncio.ensure_future(self._poll())
# run loop:
loop.run_forever()
loop.run_until_complete(loop.shutdown_asyncgens())
# cancel task:
self._poll_task.cancel()
with suppress(asyncio.CancelledError):
loop.run_until_complete(self._poll_task)
finally:
loop.close()
def stop(self):
self.loop.call_soon_threadsafe(self.loop.stop)
async def _poll(self):
while True: # you don't need to create new task each time
print('ook')
await asyncio.sleep(1.0)
hw = Hardware()
try:
hw.start()
while True:
sleep(.1)
except KeyboardInterrupt:
hw.stop()
hw.join()
【讨论】:
以上是关于线程和 asyncio:任务已销毁,但处于挂起状态的主要内容,如果未能解决你的问题,请参考以下文章
取消 asyncio 任务导致“任务被破坏但它处于挂起状态”
Python3 asyncio“任务已被破坏,但处于待处理状态”,具有某些特定条件