【问题标题】:Handle Thread/Greenlit kill in gevent在 gevent 中处理线程/Greenlit 杀死
【发布时间】:2016-05-17 13:56:11
【问题描述】:

我希望在 gevent 中创建一个非阻塞线程/Greenlit。该线程旨在运行,直到发送某种信号来停止它,此时我希望执行一个操作(保存一些数据)。

从 gevent kill docs 我希望以下代码在被杀死时打印 Done

import gevent
def myloop():
    try:
        while True:
            pass
    except gevent.greenlet.GreenletExit:
        print "Done"
thread = gevent.spawn(myloop)
thread.kill()

但是,这不会发生。关于为什么的任何想法?我做错了什么可怕的事情吗?如何实现指定的行为?

 

【问题讨论】:

    标签: python multithreading gevent


    【解决方案1】:

    由于您的 greenlet 实际上从未“阻塞”,而是永远消耗 CPU,因此它永远不会被杀死。从 gevent 的角度来看,它将被杀死,但这永远不会发生,因为 greenlet 永远不会离开它的 while 循环。

    我很确定如果您在 while 循环中添加 sleep(0)sleep 将引发 GreenletExit 并且循环将中断。

    事实上,你可以通过查看代码来推断:

    try:
        while True:
            pass
    except ...:
        ...
    

    从语法上讲,这里没有什么可以引发异常的。我们需要做一些可以提高的事情,那就是sleep(0)

    【讨论】:

    • 顺便说一句,在产卵后立即杀死一个greenlet可能会导致它永远不会被安排。尝试在thread.kill() 之前添加gevent.sleep(0),则消息应该正确显示。
    • 事实上,如果他在thread.kill() 之前添加gevent.sleep(0),我描述的行为就会发生:它会死锁,永远消耗CPU 时间。这是因为 gevent 无法修补 while True: pass 中的任何内容。
    • 附加说明:gevent 隐藏了普通函数调用和上下文切换之间的区别,这可能是原始发布者感到困惑的原因。 gevent.sleep(0) 不是“普通函数调用”,它实际上会屈服于事件循环,而 pass 不会。在其他语言(如 Node.JS)中,每个函数调用都会产生事件循环,所以这样的代码可能会终止。
    • gevent.sleep(0) 替换pass 并在thread.kill() 之前插入它可以达到我想要的效果,谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-19
    • 1970-01-01
    • 2014-06-07
    • 2014-05-17
    • 1970-01-01
    • 1970-01-01
    • 2011-04-19
    相关资源
    最近更新 更多