Как остановить цикл объекта dbus

Я пытаюсь остановить gobject.MainLoop() через несколько секунд.
Я не знаю, можно ли установить тайм-аут для такого цикла, это было бы идеально, но я не нашел этого.

Итак, я попытался обойти это с помощью многопоточности, но, к сожалению, основной цикл блокирует другие потоки.
Вот мой код (я работаю с python 2.7):

import MediaCenter_dbusConfig
import dbus
import gobject
from dbus.mainloop.glib import DBusGMainLoop
from time import sleep
from threading import Thread


mainloop=0

class Timeout(Thread):
    global mainloop

    def __init__(self):

        Thread.__init__(self)

    def run(self):
        global mainloop

        i = 0
        while i < 30:
            sleep(1)
            i += 1
        mainloop.quit()

class Loop(Thread):
    global mainloop

    def __init__(self):

        Thread.__init__(self)

    def run(self):
        global mainloop

        sleep(5)
        mainloop.run()

def catchall_detectedDevicePopUp_from_willShowPopup_signals_handler(popup_string):
    global mainloop

    if(popup_string == "DetectedDevicePopUp.qml") :
        print(popup_string)
        mainloop.quit()

def detectedDevicePopUp_detector() :
    global mainloop

    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

    bus=MediaCenter_dbusConfig.init() # basicly do a dbus.bus.BusConnection()

    bus.add_signal_receiver(catchall_detectedDevicePopUp_from_willShowPopup_signals_handler, dbus_interface = "com.orange.mediacenter.apimanager", signal_name = "willShowPopup")

    mainloop = gobject.MainLoop()

    thread1 = Timeout()
    thread2 = Loop()
    thread1.start()
    thread2.start()
    thread1.join()
    thread2.join()

Здесь я звоню detectedDevicePopUp_detector(). Я жду сигнала с именем willShowPopup. Если я получил сигнал, я хочу остановить цикл и продолжить свою программу, а через 30 с, если я не получил никакого сигнала, я хочу того же (остановить цикл и продолжить свою программу), но здесь это не работает , мой поток Timeout заблокирован моим потоком Loop.
Уточнение: я не могу редактировать отправленные сигналы (тестирую приложение).

Любые идеи ?


person Tezonis    schedule 18.01.2016    source источник


Ответы (1)


Как я понял вопрос, многопоточность на самом деле не нужна. Ниже приведен пример, который использует gobject.timeout_add для добавления максимального времени, в течение которого основной цикл будет работать, если нет сигнала для его остановки:

import gobject
import dbus
import dbus.service

from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)


OPATH = "/com/example/StopLoop"
IFACE = "com.example.StopLoop"
BUS_NAME = "com.example.StopLoop"
TIMEOUT = 30 * 1000


class Example(dbus.service.Object):
    def __init__(self, loop):
        self.loop = loop
        bus = dbus.SessionBus()
        bus.request_name(BUS_NAME)
        bus_name = dbus.service.BusName(BUS_NAME, bus=bus)
        dbus.service.Object.__init__(self, bus_name, OPATH)
        # Add a timeout for how long to run mainloop
        # if no signal is received
        self.setup_timeout(TIMEOUT)
        # Listen to the "Stop" signal
        self.listen_for_signal(bus)

    def setup_timeout(self, timeout):
        gobject.timeout_add(timeout, self.handler)

    def listen_for_signal(self, bus):
        bus.add_signal_receiver(self.handler, "Stop")

    def handler(self):
        # This handler is used for both timeout and signal
        self.loop.quit()


if __name__ == "__main__":
    loop = gobject.MainLoop()
    a = Example(loop)
    loop.run()
    print "Exited mainloop, continuing program..."

Если сигнал Stop получен, например. при выполнении:

dbus-send --session --type=signal --dest=com.example.StopLoop /com/example/StopLoop com.example.StopLoop.Stop

Основной цикл завершится, и код продолжится с того места, где был вызван loop.run().

Если сигнал не получен, основной цикл будет остановлен по тайм-ауту (в данном случае 30 секунд) и продолжится с того места, где был вызван loop.run().

person JoGr    schedule 18.01.2016