如何中断线程超时?

时间:2018-09-03 18:05:01

标签: python python-3.x multithreading

我需要写一个线程:

  • 运行 n 秒,然后执行A(然后退出)
  • 除非其父母告知其提前停止,在这种情况下,它会执行B(然后退出)

我写了一些有用但确实令人费解的东西(我相信)。它错误地使用Lock()作为标志:

import threading
import time

def countdown(lock):
    t = 0
    while t < 10:
        t += 1
        print(t)
        try:
            lock.release()
        except RuntimeError:
            # was not told to die (= lock is not set)
            pass
        else:
            # the parent notified to kill by setting the lock
            print("child: the lock has been set, means I die before timeout")
            return
        time.sleep(1)

    # executed when timeouting
    print("child: I timeouted on my own")
    return

lock = threading.Lock()
# with timeout
threading.Thread(target=countdown, args=(lock,)).start()
print("parent: sleeping 12 seconds, the thread should timeout in the meantime")
time.sleep(12)

lock = threading.Lock()
# without timeout
threading.Thread(target=countdown, args=(lock,)).start()
print("parent: sleeping 5 seconds, and then setting the flag")
time.sleep(5)
lock.acquire()
print("the counter should exit prematurely while I continue sleeping")
time.sleep(5)

它正常工作(我不关心时间的微小变化-6秒vs 5秒,因为主线程和生成的线程同时运行):

1
parent: sleeping 12 seconds, the thread should timeout in the meantime
2
3
4
5
6
7
8
9
10
child: I timeouted on my own
1
parent: sleeping 5 seconds, and then setting the flag
2
3
4
5
the counter should exit prematurely while I continue sleeping
6
child: the lock has been set, means I die before timeout

正如我提到的那样,这种解决方案在我看来非常复杂。

是否还有更多的pythonic结构可以运行超时线程,并可由其父级中断?

1 个答案:

答案 0 :(得分:1)

如果多余的线程仅用于递减计数,而不同时执行其他任何功能,则threading.Timer()对象就是为此而创建的。

如果需要,可以使用.cancel()方法提前取消计时器。可以在the official documentation中找到更多信息。

重写问题中的示例(稍作修改),代码看起来像这样:

import threading
import time

# with timeout
t = threading.Timer(10.0, lambda: print("I timed out"))
t.start()
print("Parent: Sleeping 12 seconds, the thread should timeout in the meantime")
time.sleep(12)
print("Done sleeping")

# without timeout
t = threading.Timer(10.0, lambda: print("I timed out"))
t.start()
print("Parent: Sleeping 6 seconds, and then cancel timers")
time.sleep(6)
t.cancel()
print("The counter is canceled while I continue sleeping")
time.sleep(6)
print("Done sleeping")