Цикл событий и очередь событий
Обратите внимание, что фьючерсы - это не потоки. Они не работают одновременно, и на самом деле Dart является однопоточным. Весь код Dart выполняется в цикле событий.
Цикл событий - это цикл, который выполняется до тех пор, пока активен текущий изолятор Dart. Когда вы вызываете main()
для запуска приложения Dart, изолятор создается, и он больше не активен после завершения основного метода и всех элементов в очереди событий.
Очередь событий - это набор всех функций, выполнение которых еще нужно завершить. Поскольку Dart является однопоточным, все эти функции необходимо запускать по очереди. Поэтому, когда один элемент в очереди событий завершается, начинается другой. Точное время и расписание очереди событий - это нечто более сложное, чем я могу объяснить сам.
Следовательно, асинхронная обработка важна для предотвращения блокировки одного потока каким-либо длительным выполнением. В пользовательском интерфейсе длительный процесс может вызвать визуальное раздражение и затруднить работу вашего приложения.
Фьючерсы
Фьючерсы представляют собой ценность, которая будет доступна когда-нибудь в будущем, отсюда и название. Когда создается Future, оно немедленно возвращается, и выполнение продолжается.
Обратный вызов, связанный с этим Future (в вашем случае expensiveFunction
), запускается путем добавления в очередь событий. Когда вы возвращаетесь из текущего изолята, выполняется обратный вызов и, как только это возможно, код после then
.
Потоки
Поскольку ваши Futures по определению асинхронны, и вы не знаете, когда они вернутся, вы хотите поставить свои обратные вызовы в очередь, чтобы они оставались в порядке.
Stream - это объект, который генерирует события, на которые можно подписаться. Когда вы пишете canvasElement.onClick.listen(...)
, вы запрашиваете onClick
поток MouseEvents
, на который вы затем подписываетесь с listen
.
Вы можете использовать Streams, чтобы поставить события в очередь и зарегистрировать обратный вызов для этих событий, чтобы запустить нужный вам код.
Что написать
main() {
// Used to add events to a stream.
var controller = new StreamController<Future>();
// Pause when we get an event so that we take one value at a time.
var subscription = controller.stream.listen(
(_) => subscription.pause());
var canvas = new CanvasElement();
canvas.onClick.listen((MouseEvent e) {
print("entering event handler");
var future = new Future<int>(expensiveFunction);
// Resume subscription after our callback is called.
controller.add(future.then(redrawCanvas).then(subscription.resume()));
print("done event handler");
});
}
expensiveFunction() {
for(int i = 0; i < 1000000000; i++){
//do something insane here
}
}
redrawCanvas(int value) {
//do stuff here
print("redrawing canvas");
}
Здесь мы ставим наши redrawCanvas
обратные вызовы в очередь, делая паузу после каждого щелчка мыши, а затем возобновляя работу после вызова redrawCanvas
.
Больше информации
См. Также этот отличный ответ на аналогичный вопрос.
Отличное место, чтобы начать читать об асинхронности Dart, является первая часть этой статьи о библиотеке dart: io и эту статью о библиотеке dart: async а>.
Для получения дополнительной информации о фьючерсах см. эту статью о фьючерсах.
Для получения информации о потоках см. эту статью о добавлении в потоки и эту статью о создании потоков.
person
Juniper Belmont
schedule
20.04.2013