@empty_project

Как в blender правильно дождаться выполнения потока в операторе?

У меня есть N-панель, которая содержит поля с настройками параметров подключения к FTP-серверу (хост, порт и т.д).
При клике происходит подключение к серверу. Понятное дело, подключение должно выполняться в потоке.

В андроиде есть удобный класс AsynTask, который имеет методы doInBackground и onPostExecute. В первом мы размещаем код, который работает в потоке, а второй метод запускается при окончании работы потока и туда же пробрасывается результат работы.

Вот мой класс для подключения к ftp-серверу:
class FTPConnector:
    DATA_DIRECTORY = r'C:\test'

    def __init__(self, file_name):
        self.ftp = FTP()
        self.file_name = file_name
        self.create_data_directory()
        self.PATH_TO_DATA = f'{self.DATA_DIRECTORY}\\{file_name}'

    def connectQuietly(self, host, port, user, password):
        self.tryToConnect(host, port)
        self.tryToLogin(user, password)
        self.tryToGetFile()

    @property
    def path_to_data(self):
        return self.PATH_TO_DATA

    def tryToConnect(self, host, port):
        try:
            self.ftp.connect(host, port)
        except:
            return InfoMessages.FTP.CHECK_HOST_AND_PORT

        return None

    def tryToLogin(self, user, password):
        try:
            self.ftp.login(user, password)
        except:
            return InfoMessages.FTP.CHECK_LOGIN_AND_PASSWORD

        return None

    def tryToGetFile(self):
        try:
            with open(self.PATH_TO_DATA, 'wb') as f:
                self.ftp.retrbinary('RETR ' + self.file_name, f.write)
        except:
            return InfoMessages.FTP.CHECK_FILE_NAME

        return None

    def create_data_directory(self):
        try:
            os.mkdir(self.DATA_DIRECTORY)
            print(f"{self.DATA_DIRECTORY} Directory created")
        except OSError:
            print(f"Failed to create directory {self.DATA_DIRECTORY}")


Код оператора(срабатывает при клике по кнопке):
class FTPConnOperator(bpy.types.Operator):
    bl_idname = "object.ftp_conn_op"
    bl_label = "FTP Conn Operator"
    bl_options = OperatorOptions.REGISTER

    def invoke(self, context, event):
        self.host = context.scene.HostAddressProperty.host_address_property
        self.port = context.scene.PortProperty.port_property
        self.user_name = context.scene.UserNameProperty.user_name_property
        self.password = context.scene.PasswordProperty.password_property
        self.file_name = context.scene.FileNameProperty.file_name_property
        return self.execute(context)

    def execute(self, context):
        error = self.check_fields()
        if error is not None:
            show_error_message_box(error)
            return OperatorOptions.CANCELLED

        error = self.check_connection()
        if error is not None:
            show_error_message_box(error)
            return OperatorOptions.CANCELLED
        else:
            show_ok_message_box("1. Соединение установлено\n" +
                                "2. Файл с данными найден\n" +
                                "3. Настройки сохранены")

        return OperatorOptions.FINISHED

    def check_fields(self):
        if self.port < 0:
            return InfoMessages.FTP.ENTER_CORRECT_PORT_NUMBER

        if not self.file_name.endswith('.xml'):
            return InfoMessages.FTP.CHECK_FILE_EXTENSION

        return None

    def check_connection(self):
        connector = FTPConnector(self.file_name)

        error = connector.tryToConnect(self.host, self.port)
        if error is not None:
            return error

        error = connector.tryToLogin(self.user_name, self.password)
        if error is not None:
            return error

        error = connector.tryToGetFile()
        if error is not None:
            return error

        return None


Я пробовал сделать в методе execute что-то подобное:
self.thread = Threat(target=self.check_connection)
self.thread.start()

while self.thread.is_alive():
        pass

# остальной код


Но такое решение естественно блокирует UI-поток и окно blender просто зависает. Как можно получить уведомление об окончании работы потока и при этом не заблокировать UI-поток? Т.е. чтобы я мог указать, какой метод будет вызван при окончании работы потока и уже в этом методе отобразить результат работы?
  • Вопрос задан
  • 83 просмотра
Решения вопроса 1
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы