пятница, 30 января 2009 г.

Очередь асинхронных ShaderJob не работает никак, потому что она не существует.

...По крайней мере, в документации я на сей счет ничего вразумительного не обнаружил, а на вопрос из моей предыдущей заметки не смогли ответить даже на форуме Adobe. Таким образом, я пришел к выводу, что очередь нужно реализовывать самому.

Задача оказалась довольно простой.

Вот пример класса, реализующего очередь:

package ru.dmitrykrasnov.service.shader {
  import flash.display.ShaderJob;
  import flash.events.ShaderEvent;

  public class ShaderJobQueue {
      public static const INSTANCE:ShaderJobQueue = new ShaderJobQueue();

      private var queue:Vector.<ShaderJob>;
      private var inProgress:Boolean;

      public function ShaderJobQueue() {
          if (INSTANCE != null) throw new Error("Сonstructor is locked.");
          queue = new Vector.<ShaderJob>();
      }

      public function addToQueue(shaderJob:ShaderJob):void {
          queue.push(shaderJob);
          if (!inProgress) {
              inProgress = true;
              run();
          }
      }

      private function run():void {
          var shaderJob:ShaderJob = queue.shift();
          shaderJob.addEventListener(ShaderEvent.COMPLETE, shaderJobCompleteHandler);
          shaderJob.start();
      }

      private function shaderJobCompleteHandler(event:ShaderEvent):void {
          event.target.removeEventListener(ShaderEvent.COMPLETE, shaderJobCompleteHandler);
          if (queue.length > 0) {
              run();
          } else {
              inProgress = false;
          }
      }
  }
}

При необходимости, этот класс можно использовать самостоятельно, вставив в свой код строку:

ShaderJobQueue.INSTANCE.addToQueue(shaderJob);

Но это некрасиво. Эстетики ради, можно немного усовершенствовать класс ShaderJob:

package ru.dmitrykrasnov.service.shader {
  import flash.display.Shader;
  import flash.display.ShaderJob;

  public class ShaderJobEnhanced extends ShaderJob{
      private var addedToQueue:Boolean;

      public function ShaderJobEnhanced(shader:Shader = null, target:Object = null, width:int = 0, height:int = 0) {
          super(shader, target, width, height);
      }

      public override function start(waitForCompletion:Boolean = false):void {
          if (waitForCompletion || addedToQueue) {
              super.start(waitForCompletion);
          } else {
              addedToQueue = true;
              ShaderJobQueue.INSTANCE.addToQueue(this);
          }
      }
  }
}

Тогда метод ShaderJobEnhanced.start() будет полностью соответствовать документации метода ShaderJob.start().

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

3 комментария:

  1. У вас везде угольные скобки скушались:
    private var queue:Vector.;
    queue = new Vector.();

    ОтветитьУдалить
  2. Большое спасибо за класс. Буду использовать!

    ОтветитьУдалить