Передача связанных методов в очередь

peredacha svyazannyh metodov v ochered Приемы программирования графических интерфейсов

Технически, чтобы обеспечить еще более высокую гибкость этой схемы, в приложении PyMailGUI из главы 14 с помощью этого модуля в очередь будут помещаться связанные методы — вызываемые объекты, которые, как упоминалось, хранят ссылку на функцию метода и на экземпляр объекта, что обеспечивает возможность доступа к данным объекта и другим его методам. При таком подходе программный код управления потоками выполнения в клиентском сценарии выглядит примерно так, как показано в примере 10.21 — версии реализации самотестирования из предыдущего примера, использующей классы и методы.

Пример 10.21. PP4E\Gui\Tools\threadtools-test-classes.py

#   тест очереди обработчиков, но для реализации операций используются

#   связанные методы

import time

from threadtools import threadChecker, startThread

from tkinter.scrolledtext import ScrolledText

class MyGUI:

def __init__(self, reps=3):

self.reps = reps # используется окно Tk по умолчанию

self.text = ScrolledText() # сохранить виджет в атрибуте

self.text.pack()

threadChecker(self.text) # запустить цикл проверки потоков self.text.bind(‘<Button-1>’, # в 3.x функция list необходима для lambda event: list(map(self.onEvent, range(6))) ) # получения всех # результатов map, для range — нет

def onEvent(self, i): # метод, запускающий поток

myname = ‘thread-%s’ % i startThread(

action = self.threadaction,

args = (i, ),

context = (myname,),

onExit = self.threadexit,

onFail = self.threadfail,

onProgress = self.threadprogress)

#   основная операция, выполняемая потоком

def threadaction(self, id, progress): # то, что делает поток

for i in range(self.reps): # доступ к данным в объекте

time.sleep(1) if progress: progress(i) # обработчик progress: в очередь

if id % 2 == 1: raise Exception # ошибочный номер: неудача

#   обработчики: передаются главному потоку через очередь def threadexit(self, myname):

self.text.insert(‘end’, ‘%s\texit\n’ % myname)

self.text.see(‘end’)

def threadfail(self, exc_info, myname): # имеет доступ к данным объекта self.text.insert(‘end’, ‘%s\tfail\t%s\n’ % (myname, exc_info[0])) self.text.see(‘end’)

def threadprogress(self, count, myname): self.text.insert(‘end’, ‘%s\tprog\t%s\n’ % (myname, count)) self.text.see(‘end’)

self.text.update() # допустимо: выполняется в главном потоке

if __name__ == ‘__main__’: MyGUI().text.mainloop()

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

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

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

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