簡體   English   中英

如何使用 asyncio 安排和取消任務

[英]How to schedule and cancel tasks with asyncio

我正在編寫一個客戶端 - 服務器應用程序。 連接時,客戶端向服務器發送一個“心跳”信號,例如,每秒。 在服務器端,我需要一種機制,我可以在其中添加要異步執行的任務(或協程或其他東西)。 此外,我想從客戶端取消任務,當它停止發送“心跳”信號時。

換句話說,當服務器啟動一個任務時,它有一種超時或ttl ,例如 3 秒。 當服務器收到“心跳”信號時,它會再重置計時器 3 秒,直到任務完成或客戶端斷開連接(停止發送信號)。

這是從pymotw.com上的 asyncio 教程中取消任務的示例 但是這里任務在event_loop開始之前就被取消了,不適合我。

import asyncio

async def task_func():
    print('in task_func')
    return 'the result'


event_loop = asyncio.get_event_loop()
try:
    print('creating task')
    task = event_loop.create_task(task_func())

    print('canceling task')
    task.cancel()

    print('entering event loop')
    event_loop.run_until_complete(task)
    print('task: {!r}'.format(task))
except asyncio.CancelledError:
    print('caught error from cancelled task')
else:
    print('task result: {!r}'.format(task.result()))
finally:
    event_loop.close()

您可以使用asyncio Task包裝器通過ensure_future()方法執行任務。

ensure_future將自動將您的協程包裝在Task包裝器中並將其附加到您的事件循環中。 然后, Task包裝器還將確保協程從awaitawait語句(或直到協程完成)“啟動”。

換句話說,只需將常規協程傳遞給ensure_future並將生成的Task對象分配給變量。 然后,您可以在需要停止時調用Task.cancel()

import asyncio

async def task_func():
    print('in task_func')
    # if the task needs to run for a while you'll need an await statement
    # to provide a pause point so that other coroutines can run in the mean time
    await some_db_or_long_running_background_coroutine()
    # or if this is a once-off thing, then return the result,
    # but then you don't really need a Task wrapper...
    # return 'the result'

async def my_app():
    my_task = None
    while True:
        await asyncio.sleep(0)

        # listen for trigger / heartbeat
        if heartbeat and my_task is None:
            my_task = asyncio.ensure_future(task_func())

        # also listen for termination of hearbeat / connection
        elif not heartbeat and my_task:
            if not my_task.cancelled():
                my_task.cancel()
            else:
                my_task = None

run_app = asyncio.ensure_future(my_app())
event_loop = asyncio.get_event_loop()
event_loop.run_forever()

請注意,任務適用於需要在不中斷主流程的情況下在后台繼續工作的長時間運行的任務。 如果您只需要一個快速的一次性方法,那么只需直接調用該函數即可。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM