简体   繁体   English

Celery:停止作为后台线程运行的无限循环

[英]Celery: Stop an infinite loop running as a background thread

I am trying to utilize threading.Thread with Celery to work like a daemon. 我正在尝试将threading.Thread与Celery一起使用,就像守护程序一样工作。 On a larger scope, the threads will poll hardware sensors as a part of a web UI-powered thermostat, but narrowed-down, this is the bit I'm stuck on: 在更大的范围内,线程将轮询硬件传感器,作为Web UI驱动的恒温器的一部分,但范围缩小了,这就是我要坚持的一点:

from celery import Celery
from celery.signals import worker_init
from celery.signals import worker_process_shutdown

from threading import Thread
from threading import Event

from time import sleep


class ThisClass(object):
  def __init__(self):
    self.shutdown = Event()
    self.thread = Thread(target=self.BackgroundMethod)

  def Start(self):
    self.thread.start()

  def Stop(self):
    self.shutdown.set()

  def BackgroundMethod(self):
    while not self.shutdown.is_set():
      print("Hello, world!")
      sleep(1)


this_class = ThisClass()
celery_app = Celery("tasks", broker="amqp://guest@localhost//")


@worker_init.connect
def WorkerReady(**kwargs):
  this_class.Start()


@worker_process_shutdown.connect
def StopPollingSensors(**kwargs):
  this_class.Stop()

This Celery script is supposed to create an instance of ThisClass as this_class, and run this_class.Start() when Celery starts. 该Celery脚本应该将ThisClass的实例创建为this_class,并在Celery启动时运行this_class.Start()。 When Celery is shutting down, it is supposed to call this_class.Stop(), which gracefully exits the Thread in ThisClass and Celery cleanly exits. 当Celery关闭时,应该调用this_class.Stop(),该函数优雅地退出ThisClass中的线程,而Celery干净退出。

However, when I hit Ctrl-C in Celery to signal a SIGINT, this_class's thread continues to run and Celery does not exit, even after multiple SIGTERMs are issued. 但是,当我在Celery中按Ctrl-C发出SIGINT信号时,即使发出了多个SIGTERM,this_class的线程也会继续运行,并且Celery不会退出。 What confuses me is if I slip a print statement in ThisClass.Stop, I see it. 令我困惑的是,如果我在ThisClass.Stop中插入打印语句,就会看到它。 Furthermore, if I add sleep(5); this_class.Stop() 此外,如果我添加sleep(5); this_class.Stop() sleep(5); this_class.Stop() after this_class.Start() , the thread starts and stops as expected, and Celery will exit normally when issued a SIGINT. sleep(5); this_class.Stop()之后的this_class.Start() ,线程按预期方式启动和停止,并且Celery在发出SIGINT时将正常退出。

How am I supposed to terminate threading.Thread instances in a Celery-based script? 我应该如何终止基于Celery的脚本中的threading.Thread实例?

Consider creating the Event object externally, and passing it to a Thread subclass. 考虑在外部创建Event对象,并将其传递给Thread子类。 The thread loops on the event object. 线程在事件对象上循环。 When an external function calls Event.set() , the thread loop exits out of the while loop cleanly. 当外部函数调用Event.set() ,线程循环干净地退出while循环。

import sys, time
from threading import Event, Thread, Timer


class ThisClass2(Thread):
    def __init__(self, event):
        super(ThisClass2,self).__init__()
        self.event = event

    def run(self):
        print 'thread start'
        while not self.event.wait(timeout=1.0):
            print("thread: Hello, world!")
        print 'thread done'


event2 = Event()
x = ThisClass2(event2)
x.start()

print 'okay'
time.sleep(1)

print 'signaling event'
event2.set()

print 'waiting'
x.join()

Example output: 输出示例:

thread start
okay
thread: Hello, world!
signaling event
waiting
thread done

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM