Как что-то сделать, при этом ничего не делая
Очередной загрузчик. Часть 1.
Пытаюсь каламбурить. Ну или напустить двусмысленности в название темы. В чем она может проявляться - эта двусмысленность - сейчас постараюсь объяснить. Стоит также заметить, что материал ждал публикации примерно год, просто не доходили руки. Исправляюсь =)
Итак, начнем с постановки задачи:
- нужно загружать "что-то"
- "что-то" может быть абсолютно чем угодно
- "что-то" может обрабатываться в процессе загрузки
- нужно четко контроллировать количество одновременных загрузок
- нужно уметь обрабатывать ошибки
- прогрессом загрузки каждого отдельного "что-то" можно пока пренебречь
Сначала я рассуждал так:
Цитата:
Вот нам нужно что-то загрузить, значит мы для начала сделаем интерфейс загрузчика, который будет иметь методы load(url), getContent() и еще что-то. И вот эти загрузчики нужно будет собрать вместе и контроллировать в одном СуперЗагрузчике
Цитата:
Нам не нужна загрузка вообще. Нам нужно выполнять какие-то действия в каком-то порядке. И иногда эти действия будут загрузкой, иногда нет. Нам нужна очередь!
Цитата:
Мама уходя из дома пишет список домашних дел Папе и детям. Для этого она берет конверты и подписывает каждый конверт: этот для Маши, этот для Коли, а вот этот для Папы. Внутри каждого из конвертов лежит листок бумаги со списком дел для того, кто указан на конверте.
И все же, к составляющим (а то уже килобайт текста и ни строчки кода). Начнем с интерфейса нашей команды. Только я сразу оговорюсь, что далее буду называть это заданием, а не командой. Ну да невелика разница.
Итак, интерфейс задания:
package nq.utils.task { /** * Интерфейс для заданий, выполнение которых идет по очерди * * @author gloomyBrain */ public interface ITask { /** * Проритет задания */ function get priority():int; /** * Начать выполнение задания */ function start():void; } }
package nq.utils.task { import flash.events.IEventDispatcher; /** * Событие успешного завершения задания */ [Event(name = "complete", type = "flash.events.Event")] /** * Событие прерывания задания */ [Event(name = "cancel", type = "flash.events.Event")] /** * Интерфейс для асинхронных заданий * * @author gloomyBrain */ public interface IAsyncTask extends ITask, IEventDispatcher { /** * Остановить выполнение задания */ function stop():void; } }
а) могут быть прерваны в любой момент
б) отправляют события при старте и прерывании (причина прерывания не рассматривается)
Так же стоит упомянуть о приоритетах. В постановке задачи у нас было "выполнять в каком-то порядке". Так вот, один из способов упорядочивания - это приоритеты. Чем больше приоритет, тем раньше будем выполнять задание.
Ну что, все подготовительные этапы пройдены, давайте думать как будем делать очередь заданий. Я для себя решил что это будет IEventDispatcher (то есть по природе своей асинхронный объект) с возможностью добавлять и удалять задания в любой момент. Так же, по моим представлениям, должна быть возможность регулировать количество одновременно исполняемых заданий. Да, кстати, говоря о параллельных заданиях - мы будем считать, что параллельно могут выполняться только асинхронные задания (IAsyncTask). Обычные задания (ITask) считаются выполненными, как только был вызван метод start(). То есть если проводить аналогии, то ITask - это вызов метода, а IAsyncTask - это начало ожидания собыия.
Перечень свойств очереди заданий:
- конструктор TaskQueue(maxThreads:uint = 1, usePriority:Boolean = false)
- методы start(), stop(), get isRunning() для контроля над процессом
- методы addTask(), removeTask() для планирования/удаления заданий
- ... ну и еще всякие приятные мелочи.
Не буду приводить здесь реализацию, потому как считаю это излишним. Она доступна во вложениях. Также во вложениях доступен небольшой планировщик заданий.
В следующий раз напишем загрузчик с использованием нашей очереди заданий.
Всего комментариев 9
Комментарии
![]() ![]() |
|
Очень полезно. Спасибо за оптимальный вариант
|
![]() ![]() |
|
Цитата:
Должен быть некоторый конвеер, но очень крутой.
var task:Task = new Task() .and(new FirstCommand()) .and(new SecondCommand()) .next(new ThirdCommand()) .next(new FourthCommand()); task.addEventListener(TaskEvent.TASK_COMPLETE, handleTaskComplete); task.execute(); var task:Task = new Task(); task.if_(new ConditionProvider()) .next(new FirstCommand()) .else_() .next(new SecondCommand()) .end(); task.addEventListener(TaskEvent.TASK_COMPLETE, handleTaskComplete); task.execute(); песня же) |
|
Обновил(-а) Котяра 07.12.2012 в 11:32
|
![]() ![]() |
|
Только один совет-просьба насчет оформления.
Когда выполнена вторая часть статьи, хотелось бы видеть ссылку на нее в конце первой. |
![]() ![]() |
|
Добавил ссылочку. Но вторая часть не пользуется популярностью ввиду... не знаю ввиду чего =)
|
Последние записи от gloomyBrain
- Очередной загрузчик. Часть 2. (05.12.2012)
- Очередной загрузчик. Часть 1. (04.12.2012)
- Пул объектов (31.08.2011)
- Мания чисел (08.12.2010)
- Отправка файлов на сервер (допилил) (24.10.2010)