Использование нескольких потоков выполнения с циклами time. sleep

ispolzovanie neskolkih potokov vypolneniya s ciklami time sleep Экскурсия по tkinter, часть 2

Иногда того же эффекта можно добиться выполнением анимации в потоках. Как уже говорилось выше, в целом обновлять интерфейс из порожденного потока выполнения опасно, но в данном примере этот прием действует (по крайней мере, на платформах, участвовавших в тестировании). В примере 9.32 каждая задача анимации выполняется как независимый и параллельный поток. Это означает, что при каждом нажатии клавиши O или R для запуска анимации порождается новый поток, который выполняет эту задачу.

Пример 9.32. PP4E\Gui\Tour\canvasDraw_tags_thread.py

аналогично, но анимация воспроизводится с применением циклов time.sleep, выполняемых параллельно в разных потоках, а не с помощью обработчиков событий, устанавливаемых методом after(), или одного активного цикла time. sleep; поскольку потоки выполняются параллельно, эта версия также позволяет перемещать овалы и прямоугольники _одновременно_ и не требует вызывать метод update для обновления графического интерфейса: фактически вызов метода .update() в этой версии приводит к краху, хотя некоторые методы холста можно безопасно использовать в потоках, иначе все это вообще не работало бы;

from tkinter import * import canvasDraw_tags import _thread, time

class CanvasEventsDemo(canvasDraw_tags.CanvasEventsDemo):

def moveEm(self, tag):

for i in range(5):

for (diffx, diffy) in [(+20, 0), (0, +20), (*20, 0), (0, *20)]: self.canvas.move(tag, diffx, diffy)

time.sleep(0.25) # приостанавливает только этот поток

def moveInSquares(self, tag):

_thread.start_new_thread(self.moveEm, (tag,))

if __name__ == ‘__main__’: CanvasEventsDemo() mainloop()

В этой версии возможно одновременное перемещение фигур, как и в примере 9.31, но на этот раз оно выполняется с помощью параллельных потоков. На самом деле используется та же схема, что и в первой версии time.sleep. Однако в данном случае активных потоков управления может быть несколько, поэтому периоды выполнения обработчиков перемещений могут перекрываться во времени — функция time.sleep блокирует только вызвавший ее поток, а не программу в целом.

В настоящее время этот пример прекрасно работает в Windows, но в Linux он однажды потерпел у меня неудачу — интерфейс не обновлялся при изменении его в потоках, и никаких изменений не наблюдалось до появления последующих событий. Правило, которое гласит, что желательно избегать изменения графического интерфейса в порождаемых потоках выполнения, остается верным. Обычно надежнее использовать потоки только для вычислений, а какое-либо обновление экрана производить в главном потоке (создавшем графический интерфейс). Тем не менее даже в этой модели главный поток выполнения может следить за результатами работы других потоков с помощью метода after, как в примере 9.31, не приостанавливаясь в периоды ожидания (подробнее об этом рассказывается в следующем разделе и в следующей главе).

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

Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011

Оцените статью
Секреты программирования
Добавить комментарий