Синглтон-асинхронный загрузчик задерживается при попытке завершить работу - PullRequest
0 голосов
/ 07 мая 2020

Я занимаюсь рефакторингом некоторого старого Python кода, который я унаследовал и долгое время исправлял go. Это программа GUI, которая порождает несколько процессов, которые используют одну службу AsyncDownloadService для загрузки данных из различных источников. AsyncDownloadService запускает потоки с помощью requests.get и обратных вызовов, чтобы не блокировать пользовательский интерфейс.

Я сделал AsyncDownloadService классом stati c, и он работал нормально.

Но потом я подумал, что это ' Я должен быть умным, чтобы применить шаблон Singleton, один раз создать экземпляр класса и с этого момента вызывать его везде, где он мне нужен, с помощью AsyncDownloadService(), без необходимости вводить зависимость. Я не уверен, что это на самом деле хорошая идея, но, применив шаблон Singleton, я заметил, что мое приложение не закрывается немедленно, когда его попросят (Gtk.main_quit(). Скорее всего, оно ждало, пока requests.get потоки будут fini sh.

Однако я не заметил такого поведения, когда служба была классом c stati. Есть идеи, почему это так?

Новый код (Singleton):

class SingletonType(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(SingletonType, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

class AsyncDownloadService(metaclass=SingletonType):
    def execute(self, command, response_handler):
        def _callback_with_args(response, **kwargs):
            command.response = response
            response_handler(command)

        kwargs = {
            'command': command,
            'callback': _callback_with_args
        }

        thread = Thread(target=self.download, kwargs=kwargs)
        thread.start()

    def download(self, command, callback):
        kwargs = {
            'timeout': command.timeout,
            'hooks': {'response': callback}
        }

        try:
            get(command.url, **kwargs)
        except exceptions.RequestException as e:
            command.error = "Connection error " + str(e)
            callback(None)

Старый код (stati c class):

class AsyncDownloadService():
    def execute(self, command, response_handler):
        def _callback_with_args(response, **kwargs):
            command.response = response
            response_handler(command)

        kwargs = {
            'command': command,
            'callback': _callback_with_args
        }

        thread = Thread(target=AsyncDownloadService.download, kwargs=kwargs)
        thread.start()

    @staticmethod
    def download(command, callback):
        kwargs = {
            'timeout': command.timeout,
            'hooks': {'response': callback}
        }

        try:
            get(command.url, **kwargs)
        except exceptions.RequestException as e:
            command.error = "Connection error " + str(e)
            callback(None)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...