# HG changeset patch # User Edouard Tisserant # Date 1664979017 -7200 # Node ID c3aae4c95bc1d2443889ee36a52b0e31ac82fd6a # Parent 369c3edc1a65940399785213f3a61c4b07fe1c55 Runtime: work around 1s delay added when using twisted reactor's callLater. Since wxPython4, using wxReactor from non-main thread was producing exceptions in wxWidget's C++ code. Then reactor.run() was called from main thread, and runtime's worker was delegating calls to reactor with callLater(0, callable). While this worked perfectly with wxReactor, it did introduce an unexplained 1 second delay to each worker call when using nomal linux reactors (i.e. without wxPython). As a workaround reactor runs in a thread when using twisted without wxPython diff -r 369c3edc1a65 -r c3aae4c95bc1 Beremiz_service.py --- a/Beremiz_service.py Wed Sep 14 15:24:33 2022 +0200 +++ b/Beremiz_service.py Wed Oct 05 16:10:17 2022 +0200 @@ -423,7 +423,12 @@ if havewx: from twisted.internet import wxreactor wxreactor.install() - from twisted.internet import reactor + from twisted.internet import reactor + reactor.registerWxApp(app) + else: + # from twisted.internet import pollreactor + # pollreactor.install() + from twisted.internet import reactor havetwisted = True except ImportError: @@ -432,11 +437,6 @@ pyruntimevars = {} -if havetwisted: - if havewx: - reactor.registerWxApp(app) - - if havewx: wx_eval_lock = Semaphore(0) @@ -578,26 +578,50 @@ runtime.GetPLCObjectSingleton().AutoLoad(autostart) -if havetwisted or havewx: - - waker_func = wx.CallAfter if havewx else partial(reactor.callLater,0) +if havetwisted and havewx: + + waker_func = wx.CallAfter # This orders ui loop to signal when ready on Stdout waker_func(print,"UI thread started successfully.") - # worker that copes with wx and (wx)reactor + # interleaved worker copes with wxreactor by delegating all asynchronous + # calls to wx's mainloop runtime.MainWorker.interleave(waker_func, FirstWorkerJob) try: - if havetwisted: - reactor.run(installSignalHandlers=False) - else: - app.MainLoop + reactor.run(installSignalHandlers=False) except KeyboardInterrupt: pass runtime.MainWorker.stop() +elif havewx: + + try: + app.MainLoop + except KeyboardInterrupt: + pass + +elif havetwisted: + + ui_thread_started = Lock() + ui_thread_started.acquire() + + reactor.callLater(0, ui_thread_started.release) + + ui_thread = Thread( + target=partial(reactor.run, installSignalHandlers=False), + name="UIThread") + ui_thread.start() + + ui_thread_started.acquire() + print("UI thread started successfully.") + try: + # blocking worker loop + runtime.MainWorker.runloop(FirstWorkerJob) + except KeyboardInterrupt: + pass else: try: # blocking worker loop @@ -618,6 +642,8 @@ if havetwisted: reactor.stop() + if not havewx: + ui_thread.join() elif havewx: app.ExitMainLoop()