Как работать с потоками в pygtk - PullRequest
5 голосов
/ 01 мая 2009

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

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

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

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

gtk.threads_init ()

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

Ответы [ 2 ]

12 голосов
/ 01 мая 2009

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

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

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

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

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

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

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

1 голос
/ 23 мая 2009

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

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

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

...