【问题标题】:Does concurrent.futures.as_completed yield for cancelled futures?concurrent.futures.as_completed 是否会为取消的期货产生收益?
【发布时间】:2021-04-02 18:29:20
【问题描述】:

我正在使用 ThreadPoolExecutor 同时执行多个任务,这个问题是关于优雅地取消未完成的任务。 在我看来,当我取消未完成(即尚未运行)的期货时,concurrent.futures.as_completed 永远不会产生取消的期货。尽管它的文档声明“[as_completed] 在完成时产生期货(已完成或取消的期货)。”

例子:

import concurrent.futures
import time

def do_task(t):
    time.sleep(t)
    print('task',t,'finished')
    return t

with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
    future_to_t = {executor.submit(do_task, t): t for t in range(1,6)}
    for future in concurrent.futures.as_completed(future_to_t):
        print('tasks done?',[f.done() for f in future_to_t])
        t = future_to_t[future]
        if t == 1:
            executor.shutdown(wait=False, cancel_futures=True)
            print('outstanding tasks are now cancelled')
    print('all tasks done')
print('bye')

在示例中,我将 5 个任务放入管道中,并在第一个任务完成后取消它们。由于任务 2、3 和 4 已经开始(3 个工作人员),我希望任务 5 被取消并由 as_completed 产生——但这永远不会发生。上面的代码打印:

task 1 finished
tasks done? [True, False, False, False, False]
outstanding tasks are now cancelled
task 2 finished
tasks done? [True, True, False, False, True]
task 3 finished
tasks done? [True, True, True, False, True]
task 4 finished
tasks done? [True, True, True, True, True]

然后它挂起并且永远不会到达all tasks done

我可以通过检查期货的状态并在所有期货完成后打破循环来解决这个问题 - 但这是我对 as_completed 的期望。

我做错了什么?有什么见解吗?谢谢!

跟进:

  • 如果我使用ThreadPoolExecutor.shutdown() 取消期货,它们的状态将更改为CANCELLED,而不是CANCELLED_AND_NOTIFIED,正如concurrent.futures.as_completed() 所期望的那样。
  • 如果我自己取消期货,concurrent.futures.as_completed() 将按预期工作。
  • 因此,作为一种解决方法,我使用 for f in future_to_t: f.cancel() 而不是 executor.shutdown(wait=False, cancel_futures=True)

【问题讨论】:

    标签: python python-3.x multithreading concurrency concurrent.futures


    【解决方案1】:

    我也遇到了同样的问题,也想使用executor.shutdown()。如果您不介意按顺序处理期货,而不是使用 as_completed() 并按完成时间获取期货,您可以使用 for 循环并检查状态

    for future in futures:
        if future.cancelled():
            pass
        result = future.result()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-03
      • 1970-01-01
      • 2018-12-16
      • 1970-01-01
      • 2015-12-30
      相关资源
      最近更新 更多