implemented callback warpper for execution in main thread

This commit is contained in:
iLLiCiTiT 2022-01-13 13:02:51 +01:00
parent f511538b49
commit 2944531434
3 changed files with 87 additions and 12 deletions

View file

@ -22,6 +22,7 @@ from openpype.settings import (
ProjectSettings,
DefaultsNotDefined
)
from openpype.tools.utils import WrappedCallbackItem
from .pype_info_widget import PypeInfoWidget
@ -61,21 +62,24 @@ class TrayManager:
if callback:
self.execute_in_main_thread(callback)
def execute_in_main_thread(self, callback):
self._main_thread_callbacks.append(callback)
def execute_in_main_thread(self, callback, *args, **kwargs):
if isinstance(callback, WrappedCallbackItem):
item = callback
else:
item = WrappedCallbackItem(callback, *args, **kwargs)
self._main_thread_callbacks.append(item)
return item
def _main_thread_execution(self):
if self._execution_in_progress:
return
self._execution_in_progress = True
while self._main_thread_callbacks:
try:
callback = self._main_thread_callbacks.popleft()
callback()
except:
self.log.warning(
"Failed to execute {} in main thread".format(callback),
exc_info=True)
for _ in range(len(self._main_thread_callbacks)):
if self._main_thread_callbacks:
item = self._main_thread_callbacks.popleft()
item.execute()
self._execution_in_progress = False

View file

@ -6,6 +6,7 @@ from .widgets import (
)
from .error_dialog import ErrorMessageBox
from .lib import WrappedCallbackItem
__all__ = (
@ -14,5 +15,7 @@ __all__ = (
"ClickableFrame",
"ExpandBtn",
"ErrorMessageBox"
"ErrorMessageBox",
"WrappedCallbackItem",
)

View file

@ -9,7 +9,10 @@ import avalon.api
from avalon import style
from avalon.vendor import qtawesome
from openpype.api import get_project_settings
from openpype.api import (
get_project_settings,
Logger
)
from openpype.lib import filter_profiles
@ -598,3 +601,68 @@ def is_remove_site_loader(loader):
def is_add_site_loader(loader):
return hasattr(loader, "add_site_to_representation")
class WrappedCallbackItem:
"""Structure to store information about callback and args/kwargs for it.
Item can be used to execute callback in main thread which may be needed
for execution of Qt objects.
Item store callback (callable variable), arguments and keyword arguments
for the callback. Item hold information about it's process.
"""
not_set = object()
_log = None
def __init__(self, callback, *args, **kwargs):
self._done = False
self._exception = self.not_set
self._result = self.not_set
self._callback = callback
self._args = args
self._kwargs = kwargs
def __call__(self):
self.execute()
@property
def log(self):
cls = self.__class__
if cls._log is None:
cls._log = Logger.get_logger(cls.__name__)
return cls._log
@property
def done(self):
return self._done
@property
def exception(self):
return self._exception
@property
def result(self):
return self._result
def execute(self):
"""Execute callback and store it's result.
Method must be called from main thread. Item is marked as `done`
when callback execution finished. Store output of callback of exception
information when callback raise one.
"""
if self.done:
self.log.warning("- item is already processed")
return
self.log.debug("Running callback: {}".format(str(self._callback)))
try:
result = self._callback(*self._args, **self._kwargs)
self._result = result
except Exception as exc:
self._exception = exc
finally:
self._done = True