Complete implementation of blocking mechanism waiting for signal. See #196.
This commit is contained in:
parent
b0575a1c34
commit
a520729444
|
@ -11,6 +11,7 @@ import Tkinter
|
||||||
from PyQt4 import QtCore
|
from PyQt4 import QtCore
|
||||||
import time # Just used for debugging. Double check before removing.
|
import time # Just used for debugging. Double check before removing.
|
||||||
from xml.dom.minidom import parseString as parse_xml_string
|
from xml.dom.minidom import parseString as parse_xml_string
|
||||||
|
from contextlib import contextmanager
|
||||||
|
|
||||||
########################################
|
########################################
|
||||||
## Imports part of FlatCAM ##
|
## Imports part of FlatCAM ##
|
||||||
|
@ -106,6 +107,10 @@ class App(QtCore.QObject):
|
||||||
|
|
||||||
message = QtCore.pyqtSignal(str, str, str)
|
message = QtCore.pyqtSignal(str, str, str)
|
||||||
|
|
||||||
|
# Emitted when an unhandled exception happens
|
||||||
|
# in the worker task.
|
||||||
|
thread_exception = QtCore.pyqtSignal(object)
|
||||||
|
|
||||||
def __init__(self, user_defaults=True, post_gui=None):
|
def __init__(self, user_defaults=True, post_gui=None):
|
||||||
"""
|
"""
|
||||||
Starts the application.
|
Starts the application.
|
||||||
|
@ -2138,13 +2143,22 @@ class App(QtCore.QObject):
|
||||||
|
|
||||||
return a, kwa
|
return a, kwa
|
||||||
|
|
||||||
from contextlib import contextmanager
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def wait_signal(signal, timeout=10000):
|
def wait_signal(signal, timeout=10000):
|
||||||
"""Block loop until signal emitted, or timeout (ms) elapses."""
|
"""
|
||||||
|
Block loop until signal emitted, timeout (ms) elapses
|
||||||
|
or unhandled exception happens in a thread.
|
||||||
|
|
||||||
|
:param signal: Signal to wait for.
|
||||||
|
"""
|
||||||
loop = QtCore.QEventLoop()
|
loop = QtCore.QEventLoop()
|
||||||
|
|
||||||
|
# Normal termination
|
||||||
signal.connect(loop.quit)
|
signal.connect(loop.quit)
|
||||||
|
|
||||||
|
# Termination by exception in thread
|
||||||
|
self.thread_exception.connect(loop.quit)
|
||||||
|
|
||||||
status = {'timed_out': False}
|
status = {'timed_out': False}
|
||||||
|
|
||||||
def report_quit():
|
def report_quit():
|
||||||
|
@ -2153,17 +2167,23 @@ class App(QtCore.QObject):
|
||||||
|
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
# Temporarily change how exceptions are managed.
|
||||||
oeh = sys.excepthook
|
oeh = sys.excepthook
|
||||||
ex = []
|
ex = []
|
||||||
def exceptHook(type_, value, traceback):
|
|
||||||
ex.append(value)
|
|
||||||
oeh(type_, value, traceback)
|
|
||||||
sys.excepthook = exceptHook
|
|
||||||
|
|
||||||
|
def except_hook(type_, value, traceback_):
|
||||||
|
ex.append(value)
|
||||||
|
oeh(type_, value, traceback_)
|
||||||
|
sys.excepthook = except_hook
|
||||||
|
|
||||||
|
# Terminate on timeout
|
||||||
if timeout is not None:
|
if timeout is not None:
|
||||||
QtCore.QTimer.singleShot(timeout, report_quit)
|
QtCore.QTimer.singleShot(timeout, report_quit)
|
||||||
|
|
||||||
|
#### Block ####
|
||||||
loop.exec_()
|
loop.exec_()
|
||||||
|
|
||||||
|
# Restore exception management
|
||||||
sys.excepthook = oeh
|
sys.excepthook = oeh
|
||||||
if ex:
|
if ex:
|
||||||
self.raiseTclError(str(ex[0]))
|
self.raiseTclError(str(ex[0]))
|
||||||
|
|
|
@ -14,24 +14,27 @@ class Worker(QtCore.QObject):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
# FlatCAMApp.App.log.debug("Worker Started!")
|
|
||||||
self.app.log.debug("Worker Started!")
|
self.app.log.debug("Worker Started!")
|
||||||
|
|
||||||
# Tasks are queued in the event listener.
|
# Tasks are queued in the event listener.
|
||||||
self.app.worker_task.connect(self.do_worker_task)
|
self.app.worker_task.connect(self.do_worker_task)
|
||||||
|
|
||||||
def do_worker_task(self, task):
|
def do_worker_task(self, task):
|
||||||
# FlatCAMApp.App.log.debug("Running task: %s" % str(task))
|
|
||||||
self.app.log.debug("Running task: %s" % str(task))
|
self.app.log.debug("Running task: %s" % str(task))
|
||||||
|
|
||||||
# 'worker_name' property of task allows to target
|
# 'worker_name' property of task allows to target
|
||||||
# specific worker.
|
# specific worker.
|
||||||
if 'worker_name' in task and task['worker_name'] == self.name:
|
if ('worker_name' in task and task['worker_name'] == self.name) or \
|
||||||
task['fcn'](*task['params'])
|
('worker_name' not in task and self.name is None):
|
||||||
return
|
|
||||||
|
try:
|
||||||
|
task['fcn'](*task['params'])
|
||||||
|
except Exception as e:
|
||||||
|
self.app.thread_exception.emit(e)
|
||||||
|
raise e
|
||||||
|
|
||||||
if 'worker_name' not in task and self.name is None:
|
|
||||||
task['fcn'](*task['params'])
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# FlatCAMApp.App.log.debug("Task ignored.")
|
# FlatCAMApp.App.log.debug("Task ignored.")
|
||||||
|
|
Loading…
Reference in New Issue