Запрос глубины очереди событий root.main()/Tkinter/TCLPython

Программы на Python
Anonymous
Запрос глубины очереди событий root.main()/Tkinter/TCL

Сообщение Anonymous »

У меня есть приложение, написанное с использованием пользовательского интерфейса tkinter, которое выполняет реальные действия через стек GPIO.
В качестве примера представьте, что в моем приложении есть датчик температуры, который проверяет температуру в помещении и затем имеет внешний аппаратный интерфейс с кондиционером для регулировки выходной температуры системы HVAC. Это делается простым способом с помощью стека GPIO.
Приложение имеет некоторые действия типа «критических для безопасности», которые оно может выполнять. Существует множество аппаратных блокировок, но я по-прежнему не хочу, чтобы приложение вышло из строя и заставило кондиционер работать на полную мощность и превратить мой теоретический дом в морозильную камеру.
Проблема есть всегда. ....как преобразовать приложение, управляемое событиями графического пользовательского интерфейса, в приложение с графическим интерфейсом, в котором также выполняется еще один цикл без:
  • Нарушения конструкции tkinter/tcl путем перестановки всего в «пока (true): делайте что-то» и добавляйте к нему root.update().
  • Добавление потоков в приложение, что сложно и потенциально небезопасно
Итак, я остановился на следующей архитектуре:
импортировать tkinter как tk

Код: Выделить всё

def main(args):

# Build the UI for the user
root = tk.Tk()
buttonShutDown = tk.Button(root, text="PUSH ME!")#, command=sys.exit(0))
buttonShutDown.pack()

# Go into the method that looks at inputs and outputs
monitorInputsAndActionOutputs(root)

# The main tkinter loop. NOTE, there are about 9000 articles on why you should NOT just shove everyhtnig in a loop and call root.update(). This is the corect way of doing it! Use root.after() calls!
root.mainloop()

def monitorInputsAndActionOutputs(root):

print ("checked the room temperature")
print ("adjusted the airconditioning to make comfy")
root.after(100, monitorInputsAndActionOutputs, root) # readd one event of the monitorInputsAndActionOutputs process to the tkinter / tcl queue

return None

if __name__ == '__main__':
import sys
sys.exit(main(sys.argv))
На самом деле это работает отлично, и теоретически будет работать вечно, и всем будет удобно(TM).
Однако я понимаю потенциальная проблема в том, что приложение имеет приличное количество методов, выполняющих различные настройки стиля PID замкнутого цикла (чтение, размышление, изменение, итерация), и я обеспокоен тем, что очередь событий tkinter начнет забиваться обработкой команд after() и вся система либо замедлится, либо полностью сломается, либо заморозит пользовательский интерфейс, либо сочетание всех трех действий.
Поэтому я хочу добавить что-то вроде (грубый пример кода, это, конечно, не работает):

Код: Выделить всё

def (checkQueueDepth):

myQueue = root.getQueueLength()

if(myQueue > 100 items):
doSomethingToAlertSomeone()
deprioritiseNonCriticalEventsTillThingsCalmTFDown()
Чтобы реализовать что-то подобное, мне нужно программно получить глубину очереди root/tkinter.
После долгих поисков < /p>
  • Документация tkinter
  • Документация TCL/TK
  • Исходный код tkinter
  • Остальное из stackoverflow
  • Интернет
  • Холодильник (для перекуса)
Я обнаружил, что внешний модуль не может запросить длину очереди tk, который основан на библиотеке tcl и, вероятно, реализует или расширяет их уведомитель.
Судя по коду tkinter, также не похоже, что существует какой-либо частный метод или объект/переменная, к которому я могу проникнуть через парадную дверь и опросить.
br />В-третьих, единственное «решение», которое кажется, — это потенциально реализовать новую систему уведомлений для TCL, а затем расширить ее функциональность для обеспечения этой функции. Вероятность того, что я это сделаю, равна нулю, у меня нет ни знаний, ни времени, и я бы скорее переписал все свое приложение на другом языке.
Поскольку это невозможно сделать, «правильный» путь, я подумал о том, «мы не собираемся называть это неправильным, но вполне возможно, что это так».
Я придумал что-то вроде этого:

Код: Выделить всё

def checkCodeLoops(root):

# The maximum time we will accept the queue processing to blow out to is 3 seconds.
maxDelayInQueueResponse = datetime.timedelta(seconds = 3)

# Take a note of the time now as well as the last time this method was run
lastCheckTime = checkTime
checkTime = datetime.datetime.now()

# If the time between this invocation of the checkCodeLoops method and the last one is greater than the max allowable time, panic!
if(checkTime - lastCheckTime > maxDelayInQueueResponse):
doSomethingToReduceLoad()
lockUISoUserCantAddMoreWorkToTheQueue()

# reque this method so that we can check again in 100ms (theoretically in 100ms at least - if the queue's flooded then this might never fire)
root.after_idle(100, monitorInputsAndActionOutputs, root)

return None
В целом это офигенный способ сделать это. По сути, вы добавляете работу в очередь, чтобы увидеть, занята ли очередь (глупо), а также есть еще одна проблема: если очередь переполнена, то этот код на самом деле не запустится, потому что любые события, добавленные в процесс after_idle(), являются обрабатывается только тогда, когда очередь пуста после after() и других элементов с более высоким приоритетом.
Поэтому я мог бы изменить его на root.after вместо root.after_idle, и теоретически это помогло бы, но у нас все еще есть проблема с использованием события в очереди, чтобы проверить, не работает ли очередь, что довольно глупо.
Если бы у меня был способ проверить глубину очереди, я мог бы начать внедряйте стратегии контроля нагрузки ДО того, как дело дойдет до стадии паники.
Очень хотелось бы услышать, есть ли у кого-нибудь лучший способ сделать это.

Подробнее здесь: https://stackoverflow.com/questions/785 ... ueue-depth

Вернуться в «Python»