Как работать с потоками в pygtk

У меня проблема с потоками в pygtk. Мое приложение состоит из программы, которая загружает изображения из Интернета, а затем отображает их с помощью pygtk. Проблема в том, что для того, чтобы сделать это и сохранить отзывчивость графического интерфейса, мне нужно использовать потоки.

Итак, я получил обратный вызов после того, как пользователь нажал кнопку «Загрузить изображения», и я вызываю метод для загрузки изображений, которые находятся в том же классе.

thread.start_new_thread(self.images_download, (путь,страницы)

Это не сработает. Единственный способ, которым я могу заставить свою программу попасть в поток, - это использовать

gtk.threads_init()

Прежде чем начинать любую тему. Теперь он загружает изображения, но графический интерфейс не отвечает. Я погуглил это и попытался поместить gtk.threads_enter и gtk.threads_leave вокруг потоков, но это просто не работает.


person zimio    schedule 01.05.2009    source источник


Ответы (2)


Ваш вопрос немного расплывчатый, и без ссылки на ваш фактический код трудно предположить, что вы делаете неправильно.

Так что я дам вам несколько советов, чтобы читать, а затем строить дикие предположения, основанные на опыте.

Прежде всего, вы, кажется, думаете, что вы можете поддерживать отзывчивость графического интерфейса только с помощью потоков. Это неправда. Вы также можете писать свой код асинхронно и делать все в однопоточном приложении. Twisted построен на этой модели программирования. Недавно я записал в блоге сообщение, в котором объясняю, как я создал интерфейс асинхронной задачи, и пример бегунов как для CLI, так и для GTK+. Вы можете просмотреть эти примеры, чтобы увидеть, как задачи могут быть реализованы асинхронно, а пользовательский интерфейс по-прежнему обновляется.

Во-вторых, если вы по какой-то причине предпочитаете использовать потоки, вам необходимо немного понять модель потоков GTK+.

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

Теперь о предположениях. Я предполагаю, что вы пытаетесь обновить свой пользовательский интерфейс GTK из потока и неправильно обрабатываете блокировку. Если это так, вам лучше на данный момент отложить все ваши обновления пользовательского интерфейса, которые вы хотите сделать, из потоков в основной поток, используя gobject.idle_add(). Таким образом, все вызовы пользовательского интерфейса будут выполняться из основного потока. Это более простая ментальная модель для программирования.

Как только вы почувствуете, что действительно понимаете модели многопоточности и блокировки, вы можете подумать об обновлении пользовательского интерфейса ваших потоков, но легко пропустить threads_enter()/threads_leave()

person Thomas Vander Stichele    schedule 01.05.2009

Вы можете использовать gtk.gdk.threads_init(), чтобы позволить любому потоку изменять пользовательский интерфейс с соблюдением блокировки gtk.gdk.threads_enter() и gtk.gdk.theads_leave(), но проблема в том, что это не хорошо работают на окнах. Я протестировал его на Linux и работает довольно хорошо, но мне не удалось заставить его работать на win32.

=== Редактировать ===

Я просматривал это, вы можете использовать gobject.io_add_watch, чтобы проверить, есть ли что-то в вашем сокете, взять его, а затем обновить графический интерфейс. проверьте мой пост об этом: Сокеты (и некоторые другие файлы) и PyGTK без потоков.

person markuz    schedule 23.05.2009