Периодические потоки Python с триггером по требованию - PullRequest
0 голосов
/ 16 декабря 2011

У меня есть простое приложение PyGTK. Так как мне нужно запускать несколько периодических задач для извлечения некоторых данных и обновления графического интерфейса, я расширил Thread следующим образом:

class MyThread(threading.Thread):        
    def __init__(self):
        threading.Thread.__init__(self)
        self.setDaemon(True)
        self.event = threading.Event()
        self.event.set()

    def run(self):
        while self.event.is_set():
            timer = threading.Timer(60, self._run)   
            timer.start()
            timer.join()

    def cancel(self):
        self.event.clear()

    def _run(self):
        gtk.threads_enter()
        # do what need to be done, fetch data, update GUI
        gtk.threads_leave()

Я запускаю темы в загрузчике приложения, сохраняю их в некотором списке и отменяю их перед выходом. Это работает просто отлично.

Но теперь я хочу добавить кнопку обновления, которая заставит один из потоков работать немедленно, а не ждать периода времени, если он не запущен.

Я попытался сделать это, добавив bool var в MyThread, чтобы указать, запущен поток или нет (задано до _run, сброс выполнен по завершении), а затем просто вызвать MyThread._run (), если он не запущен, но это вызывает мой Приложение перестает отвечать на запросы и запускает задачу, чтобы никогда не завершать выполнение.

Я не уверен, почему это происходит. Как лучше всего решить эту проблему? Также было бы хорошо, если бы я мог выполнять обновление в фоновом режиме, чтобы он не блокировал графический интерфейс.

Может быть, вызвать run и передать количество секунд до 1, чтобы таймер мог запустить его раньше?

1 Ответ

2 голосов
/ 19 декабря 2011

Вместо использования Timer используйте другой объект Event в сочетании с тайм-аутом.Затем вы можете установить это событие в вашем обратном вызове кнопки.Следующий код иллюстрирует это (я сократил ваш код отмены, чтобы он был коротким):

import threading

class MyThread(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)
        self.sleep_event = threading.Event()
        self.damon = True

    def run(self):
        while True:
            self.sleep_event.clear()
            self.sleep_event.wait(60)
            threading.Thread(target=self._run).start()

    def _run(self):
        print "run"

my_thread = MyThread()
my_thread.start()

while True:
    raw_input("Hit ENTER to force execution\n")
    my_thread.sleep_event.set()

По умолчанию "run" будет печататься каждые 60 секундЕсли вы нажмете ENTER, он будет напечатан сразу, а затем снова через 60 секунд и т. Д.

...