E
E
empty_project2020-08-23 12:40:26
Python
empty_project, 2020-08-23 12:40:26

How to correctly wait for the execution of a thread in a statement in blender?

I have an N-panel that contains fields with settings for connecting to an FTP server (host, port, etc.).
Clicking connects to the server. Clear business, connection should be fulfilled in a stream.

There is a handy AsynTask class in android which has doInBackground and onPostExecute methods. In the first one, we place the code that works in the thread, and the second method is launched when the thread ends, and the result of the work is also thrown there.

Here is my class for connecting to ftp server:

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}")


Operator code (fires when the button is clicked):
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


I tried to do something like this in the execute method:
self.thread = Threat(target=self.check_connection)
self.thread.start()

while self.thread.is_alive():
        pass

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


But such a solution naturally blocks the UI thread and the blender window simply freezes. How can I be notified when a thread has finished running without blocking the UI thread? Those. so that I can specify which method will be called when the thread ends and display the result of the work in this method?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
alfss, 2020-08-23
@empty_project

https://blender.stackexchange.com/questions/1050/b...

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question