def stop_daemon(server: ControlServer): nonlocal stopping if stopping: return stopping = True stop_task = asyncio.ensure_future(asyncio.wait([server.stop(), server.control.stop()])) stop_task.add_done_callback(lambda fut: loop.stop())
class ControlManagerThread(QThread): error_happened = pyqtSignal(str, Exception) def __init__(self): super().__init__() self._loop = None # type: asyncio.AbstractEventLoop self._control = ControlManager() self._control_server = ControlServer(self._control, None) self._stopping = False @property def loop(self) -> asyncio.AbstractEventLoop: return self._loop @property def control(self) -> ControlManager: return self._control def run(self): self._loop = asyncio.new_event_loop() asyncio.set_event_loop(self._loop) with closing(self._loop): self._loop.run_until_complete(self._control.start()) self._loop.run_until_complete(self._control_server.start()) try: self._control.load_state() except Exception as err: self.error_happened.emit('Failed to load program state', err) self._control.invoke_state_dumps() self._loop.run_forever() def stop(self): if self._stopping: return self._stopping = True stop_fut = asyncio.run_coroutine_threadsafe(asyncio.wait([self._control_server.stop(), self._control.stop()]), self._loop) stop_fut.add_done_callback(lambda fut: self._loop.stop()) self.wait()