当前位置: 首页 > 知识库问答 >
问题:

是否可以在异步python中暂停和重新启动任务?

廉雅惠
2023-03-14

这个问题应该很简单,但是我找不到任何关于它的东西。

我有一个异步python程序,其中包含一个运行时间相当长的任务,我希望能够在任意点挂起并重新启动(当然,任意意味着任何有wather关键字的地方)。我希望有一些类似于任务.挂起()任务.恢复()的路线,但似乎没有。在任务或事件循环级别是否有任何用于此的API,或者我需要以某种方式自己执行此操作?我不想在每次等待之前放置事件.wait() ...

谢谢

共有1个答案

勾裕
2023-03-14

你所要求的是可能的,但不是微不足道的。首先,请注意,您永远不能在每个等待时都挂起,而只能在那些导致协程挂起的挂起上挂起,例如 asyncio.sleep() 或没有准备返回数据stream.read()。等待协程立即开始执行它,如果协程可以立即返回,则它不会下降到事件循环。仅当等待方(或其等待方等)请求事件循环时,await 才会挂起到事件循环。这些问题中的更多详细信息:[1],[2],[3],[4]。

考虑到这一点,您可以使用此答案中的技术来拦截每个协程的恢复,并使用附加代码检查任务是否暂停,如果暂停,则在继续之前等待恢复事件。

import asyncio

class Suspendable:
    def __init__(self, target):
        self._target = target
        self._can_run = asyncio.Event()
        self._can_run.set()
        self._task = asyncio.ensure_future(self)

    def __await__(self):
        target_iter = self._target.__await__()
        iter_send, iter_throw = target_iter.send, target_iter.throw
        send, message = iter_send, None
        # This "while" emulates yield from.
        while True:
            # wait for can_run before resuming execution of self._target
            try:
                while not self._can_run.is_set():
                    yield from self._can_run.wait().__await__()
            except BaseException as err:
                send, message = iter_throw, err

            # continue with our regular program
            try:
                signal = send(message)
            except StopIteration as err:
                return err.value
            else:
                send = iter_send
            try:
                message = yield signal
            except BaseException as err:
                send, message = iter_throw, err

    def suspend(self):
        self._can_run.clear()

    def is_suspended(self):
        return not self._can_run.is_set()

    def resume(self):
        self._can_run.set()

    def get_task(self):
        return self._task

测试:

import time

async def heartbeat():
    while True:
        print(time.time())
        await asyncio.sleep(.2)

async def main():
    task = Suspendable(heartbeat())
    for i in range(5):
        print('suspending')
        task.suspend()
        await asyncio.sleep(1)
        print('resuming')
        task.resume()
        await asyncio.sleep(1)

asyncio.run(main())
 类似资料:
  • 在WPF应用程序中,我有一个线程池(每个线程都是对返回base 64映像的REST webservice的调用),我想精确地“控制”这些线程。 这些线程是异步的,我希望能够暂停/恢复它们中的每一个。 > < li> 我想使用CancellationToken之类的东西不是一个选项,因为每个线程都只是进行一次调用并等待响应。 我只是在课堂线程中看到的= 如果有人有什么建议呢? 提前谢谢。

  • 实现异步启动 下面是一个示例: public class MyVerticle extends AbstractVerticle { public void start(Future<Void> startFuture) { // Now deploy some other verticle: vertx.deployVerticle("com.foo.OtherVerticl

  • 问题内容: 如果我在Thread对象上使用start()并且run()方法返回,是否可以再次调用start()? 例如, 我只是想知道是因为我的代码抛出了IllegalThreadStateExceptions,所以想知道是否是因为您不能执行上述操作。 问题答案: 不,你不能。该方法的Javadoc 告诉您!

  • 嗨,我是 Android 编程的新手,我一直在看一个关于 Android 游戏编程的 youtube 教程,问题是这个特定的课程被留在了期中,所以游戏还没有完成,所以我尝试自己添加一些东西。在我的新旅程中,我一直在解决一个自己无法解决的问题,所以如果有人可以帮助我,我会在这里尝试。 问题是游戏的视觉部分,我有一个surfaceView和一个TouchEvent事件。当我暂停游戏(方法暂停活动)时出

  • C#中的许多内置IO函数是非阻塞的,也就是说,它们在等待操作完成时不会抓住线程不放。 例如,返回的是非阻塞的。 它不只是暂停它正在使用的线程,它实际上释放了线程,以便其他进程可以使用它。 我假设这是通过调用OS来实现的,这样OS在检索到文件时就回调到程序,而程序不必浪费一个线程来等待它。 是否可以自己创建一个非阻塞的异步任务? 执行类似的操作显然不会像那样释放当前线程。 我意识到Hibernate

  • 问题内容: (下面的示例代码是独立且可运行的,您可以尝试一下,它不会使系统崩溃:) Tom Hawtin在这里评论了这个问题:为什么人们在事件队列上运行JavaGUI 那: EDT不太可能崩溃。 EDT调度中抛出的未经检查的异常将被捕获,转储并且线程继续运行。 有人可以解释一下这是怎么回事(每次您单击 “引发未经检查的异常” 按钮时,都会有意除以零): 我收到以下消息(这是我期望的): 对我来说,