Могут ли потоки Python заставить их родительский/основной процесс выполнять код?

Предыстория: я написал простое приложение RUMPS/PyObjC, которое в различных точках делает HTTP-запросы и выводит диалоговые окна системных предупреждений. Большинство HTTP-запросов распределены по потокам, чтобы избежать блокировки основного выполнения.

Запрос: В PyObjC вы не должны создавать диалоговые окна предупреждений в фоновых потоках (только основной процесс может безопасно это делать), поэтому мне было интересно, есть ли разумный шаблон, который я мог бы использовать, чтобы разрешить дочернему процессу потоки для связи со своим родителем, чтобы уведомить его о том, что диалоговое окно предупреждения должно быть создано.

В качестве примера:

  1. В основной программе определен метод popAlert(), который вызывает функции PyObjC для создания диалогового окна предупреждения.
  2. Основная программа запускает поток, который выполняет HTTP-запрос и хочет вывести предупреждение по завершении.
  3. Дочерний поток, когда HTTP-запрос завершается, каким-то образом обращается к основному процессу, чтобы вызвать popAlert().

На данный момент у меня есть дочерний поток, создающий диалоговое окно предупреждения, которое, по-видимому, небезопасно в PyObjC.

Я довольно новичок в многопоточной/многопроцессорной обработке, и примеры межпотокового взаимодействия, которые я видел до сих пор, по-видимому, в основном включают дочерние потоки, получающие сообщения из механизма, подобного очереди, с родительской факультативной блокировкой, пока очередь не станет пустой. Я еще не видел ничего, что указывало бы на возможность того, чтобы родитель ответил на сообщение из дочернего потока так, как я описываю.

Если для этого требуется реархитектура, это тоже нормально — я не привержен к какому-либо конкретному многопроцессорному подходу.

Любые советы будут высоко ценится. Пожалуйста, дайте мне знать, если я могу предоставить более подробную информацию. Большое спасибо за чтение.


person BigglesZX    schedule 31.05.2014    source источник


Ответы (2)


Взгляните на pyobjc_performSelectorOnMainThread. Это может быть то, что вам нужно. Вот надуманный пример использования:

  class MyClass (NSObject):

     def divideByZero_(self, arg):
          return arg/0

     def doit(self):
         try:
             result = self.performSelectorOnMainThread_withObject_(
                  'divideByZero:', 55)
             print result

         except:
             print "Division failed"

Вы можете найти его более конкретное использование в этом примере приложения PyObjC. В частности, проверьте WSTConnectionWindowControllerClass.py.

person dano    schedule 04.06.2014
comment
Спасибо, я посмотрю этот пример приложения. - person BigglesZX; 05.06.2014

Вы также можете использовать очередь для передачи сообщений от дочерних элементов к родительским. Проблема здесь в том, что вам нужен цикл сообщений в основном потоке, который регулярно читает очередь сообщений для отображения сообщений.

person Daniel    schedule 31.05.2014
comment
см. также docs.python.org/3.4/library/ - person Aprillion; 31.05.2014
comment
@Daniel, спасибо за ваш ответ - я прав, думая, что это будет проблематично, потому что основной поток не сможет выполнять какую-либо другую работу, находясь в цикле сообщений? - person BigglesZX; 31.05.2014
comment
@BigglesZX большинство программ, предоставляющих элементы графического интерфейса, для начала построены вокруг цикла событий, потому что это то, что требуется большинству фреймворков графического интерфейса. Объект цикла событий обычно предоставляет метод add_callback (или что-то подобное), который позволяет дочерним потокам планировать запуск метода в основном потоке. - person dano; 31.05.2014
comment
@BigglesZX взгляните на pyobjc_performSelectorOnMainThread. Это может быть то, что вам нужно. - person dano; 31.05.2014
comment
@BigglesZX Вот документация для этого: pythonhosted.org/pyobjc/api/threading-helpers. html - person dano; 31.05.2014
comment
@dano Спасибо - это выглядит полезным. Я попробую. - person BigglesZX; 02.06.2014
comment
@dano У меня была трещина в этом, но пока не добился успеха - вызов pyobjc_performSelectorOnMainThread_withObject_ не может найти целевой метод, который я указываю, возможно, из-за проблемы наследования. Вы особенно разбираетесь в pyojbc? Я могу опубликовать пример кода, если это так, но если нет, я буду рад отказаться от этого занятия :) - person BigglesZX; 03.06.2014
comment
@BigglesZX, я вообще никогда не использовал pyobjc или Objective-C, извините! Только что погуглил и нашел эту ссылку. - person dano; 03.06.2014
comment
@dano - Не беспокойтесь. Каков правильный этикет SO здесь? Вы хотите добавить ответ, указывающий на документацию и методы, которые вы упомянули? Кажется справедливым, что вы получили признание, несмотря на мою проблему с этим конкретным решением прямо сейчас. - person BigglesZX; 04.06.2014