Здравствуйте все Хабра читатели, в своем первом посте решил осветить тему связанную с много-поточностью в as3, до релиза плеера 11.4, как мы помним в технологии не присутствовало поддержки много-поточностью(Worker), но в свете последних событий она наконец таки появилась.
По своей сути Worker это параллельно запущенный другой swf.
Экземпляр Worker-а создается довольно таки просто методом WorkerDomain.current.createWorker(), как параметр получающий байты SWF. Существуют три вида создания этих байтов.
Давайте непосредственно пробежимся по базовым понятиям создания каналов.
Для начала мы должны создать наш worker, у меня он выглядит так:
в Flesh Builder 4.7 разработана неплохая функция при создании класса типа worker, IDE автоматом генерирует swf из класса worker-а, а затем помещает ссылку на этот swf в класс Workers, который по своей сути ни что иное чем холдер static методов содержащие ссылки на Embed ресурсы(в нашем случаи это все swf файлы т.е. worker), соответственно Workers.org_kor_particleworker_workers_ParticleWorker это путь к файлу моего worker.
Таким образом как мы и говорили выше swf это есть наш worker(далее канал)
После создания нового канала нам надо создать связи между каналами, учитывая, что их у нас теперь стало два, текущий и тот который создали:
здесь мы создали две связи, у каждого канала есть метод createMessageChannel, который позволяет нам создать канал связи, в параметры метода нужно передать канал получатель. Условно если говорить грубым языком мы связали наши два канала так что _workerToMain получает данные от созданного канала, а _mainToWorker получает данные от главного канала.
Наш следующий шаг это расшарить данные между каналами:
Здесь мы созданному каналу передали наши классы связи, что бы иметь доступ к ним.
Ну а здесь думаю все ясно запускаем канал и слушаем канал связи отвечающий за сообщения от нашего worker.
Далее рассмотрим как будет выглядеть наш worker.
Посмотрим теперь как будет выглядеть класс нашего Worker-а. Для начала нужна создать его экземпляр, учитывая что мы уже в нем, оно будет выглядеть следующим образом:
Дальше получим ссылки на наши каналы связи:
Все просто, получили то что отправили в главном классе. Ну и в конце повесим слушатель на канал получающий данные от главного класса и отправим некое сообщение:
И уже в слушателе главного класса можно получить это сообщение, методом _workerToMain.receive(). Все довольно просто. Как вариант можно отправлять все, что угодно, начиная от ByteArray, заканчивая собственными классами, главное не забыть их сериализовать. Так же можно обмениваться данными методами setSharedProperty и getSharedProperty, точно так же как мы передавали экземпляры классов каналов связи.
В заключение исходники теста, который я переписал для проверки работы worker.
По своей сути Worker это параллельно запущенный другой swf.
Экземпляр Worker-а создается довольно таки просто методом WorkerDomain.current.createWorker(), как параметр получающий байты SWF. Существуют три вида создания этих байтов.
- 1. Создания с помощи loaderInfo.bytest, который в свою очередь передаст байты текущего SWF, этот метод самый быстрой, но он не рекомендуется.
- 2. Создания с помощи встраивания посредством тега Embed другого swf и получения его байтов.
- 3. Создания с помощи библиотеки которая позволяет классы преобразовывать в байты, библиотека называется Worker From Class
Давайте непосредственно пробежимся по базовым понятиям создания каналов.
Главный класс.
Для начала мы должны создать наш worker, у меня он выглядит так:
_worker = WorkerDomain.current.createWorker(Workers.org_kor_particleworker_workers_ParticleWorker);
в Flesh Builder 4.7 разработана неплохая функция при создании класса типа worker, IDE автоматом генерирует swf из класса worker-а, а затем помещает ссылку на этот swf в класс Workers, который по своей сути ни что иное чем холдер static методов содержащие ссылки на Embed ресурсы(в нашем случаи это все swf файлы т.е. worker), соответственно Workers.org_kor_particleworker_workers_ParticleWorker это путь к файлу моего worker.
Таким образом как мы и говорили выше swf это есть наш worker(далее канал)
После создания нового канала нам надо создать связи между каналами, учитывая, что их у нас теперь стало два, текущий и тот который создали:
_workerToMain = this._worker.createMessageChannel(Worker.current);
_mainToWorker = Worker.current.createMessageChannel(this._worker);
здесь мы создали две связи, у каждого канала есть метод createMessageChannel, который позволяет нам создать канал связи, в параметры метода нужно передать канал получатель. Условно если говорить грубым языком мы связали наши два канала так что _workerToMain получает данные от созданного канала, а _mainToWorker получает данные от главного канала.
Наш следующий шаг это расшарить данные между каналами:
_worker.setSharedProperty("workerToMain", this._workerToMain);
_worker.setSharedProperty("mainToWorker", this._mainToWorker);
Здесь мы созданному каналу передали наши классы связи, что бы иметь доступ к ним.
_workerToMain.addEventListener(Event.CHANNEL_MESSAGE, onChannelMessageFromWorker);
_worker.start();
Ну а здесь думаю все ясно запускаем канал и слушаем канал связи отвечающий за сообщения от нашего worker.
Далее рассмотрим как будет выглядеть наш worker.
Класс worker
Посмотрим теперь как будет выглядеть класс нашего Worker-а. Для начала нужна создать его экземпляр, учитывая что мы уже в нем, оно будет выглядеть следующим образом:
_worker = Worker.current;
Дальше получим ссылки на наши каналы связи:
_mainToWorker = this._worker.getSharedProperty("mainToWorker");
_workerToMain = this._worker.getSharedProperty("workerToMain");
Все просто, получили то что отправили в главном классе. Ну и в конце повесим слушатель на канал получающий данные от главного класса и отправим некое сообщение:
_mainToWorker.addEventListener(Event.CHANNEL_MESSAGE, onChannelMessageFromMain);
_workerToMain.send(" --- Worker started!!! --- ");
И уже в слушателе главного класса можно получить это сообщение, методом _workerToMain.receive(). Все довольно просто. Как вариант можно отправлять все, что угодно, начиная от ByteArray, заканчивая собственными классами, главное не забыть их сериализовать. Так же можно обмениваться данными методами setSharedProperty и getSharedProperty, точно так же как мы передавали экземпляры классов каналов связи.
В заключение.
В заключение исходники теста, который я переписал для проверки работы worker.