当前位置: 首页 > 面试题库 >

asyncio:是否可以取消由执行者执行的未来?

慎弘化
2023-03-14
问题内容

我想使用asyncio调用loop.run_in_executor在Executor中启动一个阻塞函数,然后在以后取消它,但这似乎对我不起作用。

这是代码:

import asyncio
import time

from concurrent.futures import ThreadPoolExecutor


def blocking_func(seconds_to_block):
    for i in range(seconds_to_block):
        print('blocking {}/{}'.format(i, seconds_to_block))
        time.sleep(1)

    print('done blocking {}'.format(seconds_to_block))


@asyncio.coroutine
def non_blocking_func(seconds):
    for i in range(seconds):
        print('yielding {}/{}'.format(i, seconds))
        yield from asyncio.sleep(1)

    print('done non blocking {}'.format(seconds))


@asyncio.coroutine
def main():
    non_blocking_futures = [non_blocking_func(x) for x in range(1, 4)]
    blocking_future = loop.run_in_executor(None, blocking_func, 5)
    print('wait a few seconds!')
    yield from asyncio.sleep(1.5)

    blocking_future.cancel()
    yield from asyncio.wait(non_blocking_futures)



loop = asyncio.get_event_loop()
executor = ThreadPoolExecutor(max_workers=1)
loop.set_default_executor(executor)
asyncio.async(main())
loop.run_forever()

我希望上面的代码仅允许阻塞函数输出:

blocking 0/5
blocking 1/5

然后查看非阻塞函数的输出。但是,即使我取消了,阻碍性的未来仍在继续。

可能吗?还有其他方法吗?

谢谢


问题答案:

在这种情况下,Future一旦它真正开始运行,就无法取消它,因为您依赖的行为concurrent.futures.Future,并且它的文档指出以下内容:

cancel()

尝试取消呼叫。 如果该调用当前正在执行并且无法取消,则该方法将返回False,否则,该调用将被取消并且该方法将返回True

因此,唯一成功的取消操作是如果任务仍在中等待执行Executor。现在,您实际上正在使用asyncio.Future包裹concurrent.futures.Future,并且在实践中,即使基础任务实际上已经在运行,如果您在调用后尝试asyncio.Future返回,byloop.run_in_executor()也会引发a
。但是,它 实际上 并不会取消中的任务执行。CancellationError``yield from``cancel() __Executor

如果需要实际取消任务,则需要使用更常规的方法来中断线程中正在运行的任务。具体操作方式取决于用例。对于示例中显示的用例,可以使用threading.Event

def blocking_func(seconds_to_block, event):
    for i in range(seconds_to_block):
        if event.is_set():
            return
        print('blocking {}/{}'.format(i, seconds_to_block))
        time.sleep(1)

    print('done blocking {}'.format(seconds_to_block))


...
event = threading.Event()
blocking_future = loop.run_in_executor(None, blocking_func, 5, event)
print('wait a few seconds!')
yield from asyncio.sleep(1.5)

blocking_future.cancel()  # Mark Future as cancelled
event.set() # Actually interrupt blocking_func


 类似资料:
  • 我有一个,它将计算出的数据转发到: 我希望客户端/用户能够取消任务: 这不起作用,因为这将取消外部的,而不是executor服务中计划的内部未来。 是否有可能将外部未来的传播到内部未来?

  • 我试图理解java中完整期货的非阻塞回调性质 有了上面的代码,我总是看到下面看到的输出 线程名称ForkJoinPool.common池工人-1 thenApply Thread name main thenApply Thread name main thenAcceptThread name main Thread name main 这个顺序似乎建议主线程等待所有Futures线程的执行。

  • 问题内容: 是否有可能以某种方式停止或终止JavaScript,从而防止再次发生基于JavaScript的执行,而无需重新加载浏览器? 我在想JavaScript等同于PHP。 问题答案: 简短答案: 如果您想了解更多,请继续阅读。 您是否要停止JavaScript的开发/调试工作? 代码中的表达式将停止页面执行,然后您的浏览器开发人员工具将使您可以查看页面冻结时的状态。 您是否要故意停止设计您的

  • 问题内容: 简而言之,我需要能够将已编译的可执行文件粘贴到Java jar文件中,然后能够从Java运行它(可能通过)。 的 原因 ,是我想使用Java来包裹ImageMagick的可执行文件成分的图像处理弹性的Map Reduce任务。EMR只希望获取一个jar文件,因此我认为没有空间在旋转的数据节点上安装软件。 问题答案: jar中的可执行文件是一种资源,您可以通过Stream访问它,并将可执

  • 问题内容: 我必须转换一个传递查询的MSSQL存储过程: 这不起作用。我敢肯定,而不是MySQL的命令,但也不管用。 有谁知道是否有可能为MySQL提供类似JavaScript的功能? 问题答案: EXECUTE是MySQL中的有效命令。MySQL参考手册

  • 问题内容: 我正在寻找一种在客户端(即在浏览器中)进行traceroute的方法。 据我所知,不可能通过Javascript或Flash发送具有任意TTL值的ICMP,UDP或TCP数据包。我知道Flash允许通过Actionscript中的Socket类进行TCP连接,但是它对于traceroute实现似乎没有用。 是开发浏览器插件的唯一解决方案吗? 编辑 :我刚刚发现它已经用Java小程序完成