Гибкий эквивалент ProcessMessages и неотзывчивый пользовательский интерфейс во время длинных циклов - PullRequest
11 голосов
/ 18 февраля 2009

Я обнаружил, что пользовательский интерфейс моего приложения Flex перестает отвечать во время очень длинных циклов обработки (десятки секунд). Например, при обработке очень больших XML-файлов и выполнении чего-то для каждого элемента ...

Есть ли эквивалент "ProcessMessages"? То есть вызов, который сказал бы Flex продолжать отвечать на события пользовательского интерфейса, даже в середине какого-то длинного цикла, чтобы пользовательский интерфейс не стал не отвечающим?

Я знаю, что Flex имеет однопоточную конструкцию . Именно поэтому я ищу что-то вроде ProcessMessages () - функцию, которая позволяет однопоточным повторно входящим приложениям (как в VB или однопоточным приложениям на основе цикла сообщений C ++) оставаться отзывчивыми во время длительных операций. ,

Сводка ответов

  1. В Flex нет встроенной функции, такой как HandleEvents() или ProcessMessages().
  2. Использование своего рода механизма обратного вызова для итеративной обработки фрагментов длинного вычислительного процесса, в то же время уступая среде выполнения между фрагментами, что позволяет ему быть отзывчивым, является единственным способом поддержания отзывчивого пользовательского интерфейса во время длинных вычислений.
  3. Способы выполнения вышесказанного:
    1. Использование события enterFrame, которое вызывается всякий раз, когда слой Flash-фильма под приложением Flex обновляет свой кадр (что-то вроде 20fps).
    2. Использование таймера.
    3. Использование UIComponent.callLater(), которое планирует работу "позже". (как документы говорят : Queues a function to be called later. Before each update of the screen, Flash Player or AIR calls the set of functions that are scheduled for the update.
    4. Использование преднамеренно запускаемых событий мыши / клавиатуры для создания псевдо "рабочих потоков", как в в этом примере .

Если есть дальнейшие предложения или если я что-то пропустил, пожалуйста, не стесняйтесь редактировать этот (сейчас) вики.

Ответы [ 5 ]

6 голосов
/ 18 февраля 2009

Проблема заключается в том, что Flash является однопоточным, то есть до тех пор, пока не будет запущена часть кода, никакая другая обработка не может быть выполнена. Вам как-то понадобится разбить обработку на более мелкие порции и выполнить эти порции, скажем, в событии enterFrame.

Редактировать : Боюсь, что отрицание этого (или симоновского) ответа не меняет того факта, что это невозможно в AS3. Прочитайте эту статью для более глубокого понимания проблемы. Статья также включает в себя простую «библиотеку» под названием PseudoThread, которая помогает в выполнении длинных фоновых вычислений. Тем не менее, вам все равно придется разбить проблему на более мелкие части.

4 голосов
/ 18 февраля 2009

Я могу вам однозначно сказать, что в Flex 3 нет встроенной конструкции, аналогичной функциональности ProcessMessages, которую вы описываете.

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

После того, как вы все заработаете, вы можете провести некоторое тестирование и профилирование, чтобы выяснить, может ли ваше приложение выполнить выполнение нескольких рабочих перед вызовом callLater(), и инкапсулировать эту логику в администраторе очередей рабочих. Например, в нашей реализации этого шаблона (с несколькими сотнями рабочих в очереди) мы смогли быстрее выполнить обработку с сопоставимой воспринимаемой производительностью, выполнив 4 рабочих перед тем, как «уступить основному потоку» с callLater(), но это полностью зависит от объема и характера работы, которую выполняют ваши работники.

2 голосов
/ 18 февраля 2009

Actionscript является однопоточным по дизайну, никакое количество ответов на голосование не изменит это.

Для обеспечения совместимости лучше всего попытаться разделить обработку на более мелкие куски и выполнять ее итеративно.

Если вам абсолютно необходима многопоточность, можно вроде сделать во Flash Player 10 с использованием фильтров Pixel Bender . Они будут выполняться в отдельном потоке и могут дать вам обратный вызов, как только они будут сделаны.
Я считаю, что они хорошо подходят для «жестких» задач обработки, поэтому они могут хорошо соответствовать вашей цели. Тем не менее, они будут предъявлять к вашему коду целый ряд требований, так что в любом случае вам лучше будет выполнять небольшие «бочки» вычислений.

2 голосов
/ 18 февраля 2009

Модель процесса для ActionScript является однопоточной, поэтому ответ - нет. Лучше всего либо отложить выполнение асинхронной задачи на сервере, если вы можете, либо вызвать курсор ожидания во время выполнения длинного цикла, либо разбить ваш процесс на несколько более мелких частей, которые не столь навязчивы для пользовательского интерфейса, или выполнить длительные задачи в момент, когда пользователь с меньшей вероятностью почувствует эффект (например, при запуске приложения).

1 голос
/ 19 февраля 2009

Нет эквивалентной функциональности во Flash Player. По своему дизайну Flash Player чередует рендеринг на экран, а затем запускает весь код для каждого кадра. Использование Event.ENTER_FRAME событий на экранных объектах или Timer объектов в других местах - лучший выбор для разбивки очень длинных вычислений.

Стоит отметить, что некоторые события в ActionScript имеют функцию updateAfterEvent() со следующим описанием:

Указывает, что Flash Player или среда выполнения AIR должны отображаться после завершения обработки этого события, если список отображения был изменен.

В частности, TimerEvent, MouseEvent и KeyboardEvent поддержка updateAfterEvent(). Могут быть и другие, но это те, которые я нашел с помощью быстрого поиска.

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