PyQt: доступ к объектам при использовании потоков - PullRequest
1 голос
/ 05 июля 2011

В настоящее время я работаю над небольшим редактором уценок , но у меня проблема:

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

Как я могу использовать многопоточность (подпроцесс, QThread) для достижения чего-то вроде следующего?

  1. При изменении текста во время обработки задание помещается в очередь.Если очередь уже содержит задание, это задание заменяется новым.
  2. При изменении текста, когда в очереди нет задания, выполняется новое задание.
  3. По завершении задания, задание из очереди выполняется.Если ничего там нет, все готово.

Уточнение

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

  1. Пользователь начинает изменять текст.
  2. Задание на рендеринг текущего текста запускается в другом потоке.
  3. Как только он заканчивается, и отрендеренный HTML заменил старый HTML, определяется, нужно ли еще делать рендеринг, т.е.самый новый текст был только что обработан или более старая версия.
  4. Если текст и рендеринг все еще не синхронизированы, перейдите к пункту 2.

Обратите внимание, что алгоритм выше Уточнение это способ сделать это с помощью 3. (определение асинхронности) как 1-thread-queue.Также обратите внимание, что на самом деле должна выполняться только самая новая работа, но я также хочу, чтобы случайные промежуточные задания были завершены, чтобы не допустить одновременной вставки огромного куска нового типа контента.

Наилучший сценарий: whileбыстро и непрерывно печатая на огромном документе, представление рендеринга обновляется каждые несколько слов или около того, в то время как редактор постоянно реагирует.

Ответы [ 2 ]

2 голосов
/ 05 июля 2011

Для меня это выглядит как работа для QThreadPool и QRunnable:

  • Создайте класс, производный от QRunnable, описывающий «визуализацию»
  • Создайте QThreadPool с maxThreadCount, установленным в 1 (очень важно, потому что одновременно должен быть только один поток рендеринга).
  • Каждый раз, когда текст изменяется, создайте экземпляр своего класса «render job» (возможно, с включенным autoDelete) и добавьте его в пул потоков с помощью QThreadPool.start(). QThreadPool поддерживает свою очередь ожидающих заданий, поэтому новое задание не теряется, если в данный момент выполняется другое задание. В этом случае он выполняется после завершения текущих заданий.

Чтобы ограничить количество созданных заданий рендеринга, вы не должны запускать задания непосредственно по сигналам .textChanged, а косвенно через QTimer. Каждый раз, когда текст меняется, перезапускайте таймер с интервалом в 500 мсек и запускайте новое «задание рендеринга», только если таймер действительно выдает .timeout.

При реализации класса "render job" не забудьте напрямую не обращаться к любому классу GUI. Вместо этого, определите сигнал в вашем классе «render job», который генерируется с отображаемой HTML-строкой в ​​качестве аргумента, как только рендеринг закончится, и подключите его к .setText() вашего виджета отображения.

Это не совсем то, что вы просили, потому что текущее задание рендеринга никогда не прерывается, а всегда завершается. Таким образом, предварительный просмотр может быть в определенной степени несинхронизирован, если текст изменяется очень быстро (например, пользователь удерживает клавишу Backspace). Тем не менее, я думаю, что это самое простое и прямолинейное решение вашей проблемы, поскольку оно не требует ни блокировки, ни синхронизации, ни отслеживания выполняемых в данный момент заданий. Каждое задание выполняется по-настоящему асинхронно в стиле «запусти и забудь».

0 голосов
/ 05 июля 2011

Что делать при каждом изменении текста: Проверьте, работает ли поток рендеринга (пометить), а если нет: дайте ему визуализировать копию содержимого текстового редактора. И поток рендеринга проверяет текущее содержимое редактора по сравнению с его последним вводом в конце каждого рендеринга. Если есть разница: пересдача.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...