Как работать с потоками в pygtk
У меня проблема с потоками в pygtk. Мое приложение состоит из программы, которая загружает изображения из Интернета, а затем отображает их с помощью pygtk. Проблема в том, что для того, чтобы сделать это и сохранить отзывчивость GUI, мне нужно использовать потоки.
Поэтому я получил обратный вызов после того, как пользователь нажал кнопку "Загрузить изображения", и я вызываю метод для загрузки изображений, которые находятся в том же классе.
thread.start_new_thread (self.images_download, (путь, страницы)
Это не сработает. Единственный способ получить мою программу - это использовать
gtk.threads_init()
Перед началом любой темы. Теперь он загружает картинки, но графический интерфейс пользователя не отвечает. Я гуглил это и попытался поместить gtk.threads_enter и gtk.threads_leave вокруг потоков, но это просто не работает.
2 ответа
Ваш вопрос немного расплывчатый, и без ссылки на ваш реальный код трудно предположить, что вы делаете неправильно.
Поэтому я дам вам несколько советов для чтения, а затем рассуждаю на основе опыта.
Прежде всего, вы, кажется, думаете, что вы можете поддерживать адаптивный интерфейс только с помощью потоков. Это неправда. Вы также можете писать свой код асинхронно и делать все в однопоточном приложении. Twisted построен на этой модели программирования. Недавно я сделал пост в блоге, в котором объясняется, как я создал асинхронный интерфейс задач, и приводим примеры бегунов для CLI и GTK+. Вы можете посмотреть на эти примеры, чтобы увидеть, как задачи могут быть реализованы асинхронно, и пользовательский интерфейс все еще обновляется.
Во-вторых, если вы по какой-то причине предпочитаете использовать потоки, вам нужно немного понять модель потоков GTK+.
Вам следует начать с чтения часто задаваемых вопросов по теме PyGTK, и вам может показаться, что этот блог тоже легко понять.
Теперь о спекуляции. Я предполагаю, что вы пытаетесь обновить свой GTK UI из потока, а не обрабатываете блокировку должным образом. Если это так, вам лучше отложить все обновления вашего пользовательского интерфейса, которые вы хотите сделать, из потоков в основной поток с помощью gobject.idle_add(). Таким образом, все вызовы пользовательского интерфейса будут выполняться из основного потока. Это более простая ментальная модель для подражания в вашем программировании.
Как только вы почувствуете, что действительно понимаете модели потоков и блокировок, вы можете рассмотреть возможность обновления пользовательского интерфейса из ваших потоков, но легко пропустить thread_enter()/threads_leave()
Вы можете использовать gtk.gdk.threads_init(), чтобы позволить любому потоку изменять интерфейс с соответствующими gtk.gdk.threads_enter() и gtk.gdk.theads_leave(), но проблема в том, что хорошо работать на окнах. Я протестировал его на Linux и работает довольно хорошо, но мне не повезло, что он работал над win32.
=== Редактировать ===
Я просматривал это, вы можете использовать gobject.io_add_watch, чтобы проверить, есть ли что-то в вашем сокете, взять его и затем обновить GUI. проверьте мой пост об этом: сокеты (и некоторые другие файлы) и PyGTK без потоков.