2015-04-21 8 views
5

Я пытаюсь реализовать звонок, который работает в фоновом режиме. Как создать нанизанные на интервале вызова скажем, каждые 30 секунд, что вызывает следующую функцию:Как создать фоновый поток на вызов функции интервала в python?

self.mqConn.heartbeat_tick() 

Кроме того, как бы я остановить эту тему?

Большое спасибо.

ответ

6

Используйте нить, содержащей петлю

from threading import Thread 
import time 

def background_task(): 
    while not background_task.cancelled: 
     self.mqConn.heartbeat_tick() 
     time.sleep(30) 
background_task.cancelled = False 

t = Thread(target=background_task) 
t.start() 

background_task.cancelled = True 

В качестве альтернативы, вы можете подклассы таймера, чтобы отменить легко:

from threading import Timer 

class RepeatingTimer(Timer): 
    def run(self): 
     while not self.finished.is_set(): 
      self.function(*self.args, **self.kwargs) 
      self.finished.wait(self.interval) 


t = RepeatingTimer(30.0, self.mqConn.heartbeat_tick) 
t.start() # every 30 seconds, call heartbeat_tick 

# later 
t.cancel() # cancels execution 
+1

Это может быть важно отметить, что это * не * выполнять через каждые 30 секунд, если 'heartbeat_tick()' занимает значительное количество времени – goncalopp

+0

Да, это будет по крайней мере 30 секунд каждый раз. Не более 30 секунд - битка сложнее. – Eric

+1

Если ваша функция переднего плана была связана с ЦП, можно ли предотвратить фоновый поток от выполнения GIL? –

2

Один из способов сделать это было бы использовать рамки circuits приложения вроде этого:

from circuits import Component, Event, Timer 


class App(Component): 

    def init(self, mqConn): 
     self.mqConn = mqConn 
     Timer(30, Event.create("heartbeat"), persist=True).register(self) 

    def heartbeat(self): 
     self.mqConn.heartbeat_tick() 


App().run() 

Примечание: Я автор схем :)

Это лишь основная идея и структура - вам нужно будет адаптировать это в соответствии с вашими точными требованиями и требованиями!

1

Или вы могли бы использовать класс Timer в модуле потоковой :

from threading import Timer 

def hello(): 
    print "hello, world" 

t = Timer(30.0, hello) 
t.start() # after 30 seconds, "hello, world" will be printed 
t.cancel() # cancels execution, this only works before the 30 seconds is elapsed 

Это не будет запускаться каждые x секунд, а скорее задерживает поток для выполнения за x секунд. Но вы все равно можете поместить это в цикл и использовать t.is_alive(), чтобы увидеть его статус.

+0

Куда бы петля шла? – Eric

+0

Это будет зависеть от варианта использования? – Joe

+0

Разве это не должно быть в фоновом потоке? – Eric

2

Быстрый ответ на вопрос Eric: вы не можете подкласса Timer, так как на самом деле это оболочка световой функции вокруг истинного класса: _Timer. Если вы это сделаете, вы получите сообщение об ошибке, которое появится в this post.

Использование _Timer вместо фиксирует это:

from threading import _Timer 

class RepeatingTimer(_Timer): 
    def run(self): 
     while not self.finished.is_set(): 
      self.function(*self.args, **self.kwargs) 
      self.finished.wait(self.interval) 


t = RepeatingTimer(30.0, self.mqConn.heartbeat_tick) 
t.start() # every 30 seconds, call heartbeat_tick 

# later 
t.cancel() # cancels execution