在一个线程中创建异步事件循环并在另一个线程中运行它同时能够从线程外部取消它是否安全(python3)

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

我想知道在一个线程中创建异步事件循环并在另一个线程中运行该循环是否安全,同时能够从运行事件循环的线程外部取消它。我想在线程中运行异步函数,同时还能够从线程外部取消它

这是我当前使用的代码,我想知道这是否是正确的方法,或者是否有更简单/更好的方法来做到这一点

import asyncio
from concurrent.futures import ThreadPoolExecutor, CancelledError
import time

pool = ThreadPoolExecutor()
loop = asyncio.new_event_loop()


def start_event_loop(loop):
    asyncio.set_event_loop(loop)  # is this necessary?
    loop.run_forever()


pool.submit(start_event_loop, loop)


async def long_task():
    try:
        while True:
            print("Running...")
            await asyncio.sleep(1)
    except asyncio.CancelledError:
        print("Task was cancelled")


future = asyncio.run_coroutine_threadsafe(long_task(), loop)

time.sleep(5)
loop.call_soon_threadsafe(future.cancel)

try:
    future.result()
except CancelledError:
    time.sleep(1)
    print("Future was cancelled")

loop.call_soon_threadsafe(loop.stop)  # can i reuse the loop?

while loop.is_running():
    print("Wating for loop to stop...")
    time.sleep(0.1)

loop.close() # is this necessary?
print("Loop stopped")

这是基于这篇文章和这个问题

我还想问一些额外的问题,那就是

  1. 有必要使用asyncio.set_event_loop吗?它们都产生相同的输出

  2. 停止事件循环后是否可以重用事件循环,或者我应该在停止循环后每次创建一个新循环。

  3. 用完后是否需要关闭循环。

python python-3.x multithreading asynchronous python-asyncio
1个回答
0
投票

更简单的方法:

import asyncio
import threading
import time

def start_event_loop(loop):
    asyncio.set_event_loop(loop)
    loop.run_forever()

async def long_task():
    try:
        while True:
            print("Running...")
            await asyncio.sleep(1)
    except asyncio.CancelledError:
        print("Task cancelled")

# An event loop as a separate thread
loop = asyncio.new_event_loop()
thread = threading.Thread(target=start_event_loop, args=(loop,), daemon=True)
thread.start()

# Schedule task in event loop
future = asyncio.run_coroutine_threadsafe(long_task(), loop)

# Simulate some work & cancel after 5 seconds
time.sleep(5)
loop.call_soon_threadsafe(future.cancel)

try:
    future.result()  # Wait for task to finish & check for exceptions
except asyncio.CancelledError:
    print("Future cancelled")

# Stop & close loop
loop.call_soon_threadsafe(loop.stop)
thread.join()  # Wait for thread to exit
loop.close()
print("Loop stopped")
  1. asyncio.get_event_loop()
    行可以跳过。

  2. 使用

    loop.stop
    停止循环后,重新使用它是不安全的。您可以使用
    asyncio.new_event_loop
    创建新循环。

  3. 是的,需要关闭循环才能正确释放资源。

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