Threading.py 1.5 KB

12345678910111213141516171819202122232425262728293031323334
  1. import threading
  2. from cura.CuraApplication import CuraApplication
  3. #
  4. # HACK:
  5. #
  6. # In project loading, when override the existing machine is selected, the stacks and containers that are correctly
  7. # active in the system will be overridden at runtime. Because the project loading is done in a different thread than
  8. # the Qt thread, something else can kick in the middle of the process. One of them is the rendering. It will access
  9. # the current stacks and container, which have not completely been updated yet, so Cura will crash in this case.
  10. #
  11. # This "@call_on_qt_thread" decorator makes sure that a function will always be called on the Qt thread (blocking).
  12. # It is applied to the read() function of project loading so it can be guaranteed that only after the project loading
  13. # process is completely done, everything else that needs to occupy the QT thread will be executed.
  14. #
  15. class InterCallObject:
  16. def __init__(self):
  17. self.finish_event = threading.Event()
  18. self.result = None
  19. def call_on_qt_thread(func):
  20. def _call_on_qt_thread_wrapper(*args, **kwargs):
  21. def _handle_call(ico, *args, **kwargs):
  22. ico.result = func(*args, **kwargs)
  23. ico.finish_event.set()
  24. inter_call_object = InterCallObject()
  25. new_args = tuple([inter_call_object] + list(args)[:])
  26. CuraApplication.getInstance().callLater(_handle_call, *new_args, **kwargs)
  27. inter_call_object.finish_event.wait()
  28. return inter_call_object.result
  29. return _call_on_qt_thread_wrapper