таймер дротика идет не так?

Это моя первая программа на Dart, и я просто хотел увидеть ее асинхронные возможности. Зная javascript, я написал следующий код:

import 'dart:async' show Timer;
import 'dart:math';

void main() {
  //Recursion
  fib1(x) => x > 1 ? fib1(x-1) + fib1(x-2) : x;
  //Mathematical
  num fi = (1 + sqrt(5)) / 2;
  fib2(x) => x > 1 ? ((pow(fi, x) + pow(1 - fi, x)) / sqrt(5)).round() : x;
  //Linear
  fib3(x) {
    if(x < 2) return x;
    int a1  = 0;
    int a2  = 1;
    int sum = 0;
    for(int i = 1; i < x; i++) {
      sum = a2 + a1;
      a1 = a2;
      a2 = sum;
    }

    return sum;
  }

  Timer.run(() => print('Fib1:' + fib1(41).toString()));
  Timer.run(() => print('Fib2:' + fib2(41).toString()));
  Timer.run(() => print('Fib3:' + fib3(41).toString()));
}

а вывод в редакторе дротиков:

Fib1:165580141
Fib2:165580141
Fib3:165580141

Все 3 вывода печатаются одновременно. Это не так? fib3 намного быстрее и должен быть напечатан первым.


person Theofilos Mouratidis    schedule 07.01.2014    source источник


Ответы (1)


Асинхронность не означает многопоточность. Dart работает однопоточным. Вы можете создавать изоляты для параллельного запуска кода.

Когда вы добавляете распечатку

{
  //...
  Timer.run(() => print('Fib1:' + fib1(41).toString()));
  Timer.run(() => print('Fib2:' + fib2(41).toString()));
  Timer.run(() => print('Fib3:' + fib3(41).toString()));
  print('exit');
}

после ваших трех Timer.run(... операторов вы получите представление о том, что такое async.

Закрытие, которое вы предоставляете с помощью Timer.run(...), планируется для более позднего выполнения, и выполняется следующий оператор вашего main. Как только цикл событий успевает обработать запланированные задачи, ваши закрытия выполняются одно за другим.

Более подробную информацию можно найти здесь: The Event Loop и Dart

** РЕДАКТИРОВАТЬ **

Когда вы запустите его таким образом, вывод может иметь для вас больше смысла

  Timer.run(() => print('Fib1: ${new DateTime.now()} - result: ${fib1(41)}'));
  Timer.run(() => print('Fib2: ${new DateTime.now()} - result: ${fib2(41)}'));
  Timer.run(() => print('Fib3: ${new DateTime.now()} - result: ${fib3(41)}'));
  print('exit');

** вывод **

exit
Fib1: 2014-01-07 12:00:46.953 - result: 165580141
Fib2: 2014-01-07 12:00:56.208 - result: 165580141
Fib3: 2014-01-07 12:00:56.210 - result: 165580141

Дело не в том, что более быстрая задача заканчивается первой. Timer.run() планирует для последующего выполнения, и выполнение main() продолжается. Когда цикл обработки событий возвращает управление потоком программы, он выполняет запланированные задачи одну за другой и одну за другой.

Возможно, вывод каким-то образом буферизируется окном вывода DartEditor или оболочкой и отображается партиями. Это может создать впечатление, что результаты распечатываются сразу.

** РЕДАКТИРОВАТЬ 2 **

Я только что увидел, что результаты пишутся один за другим. Легко проверить, переместите ли вы медленный Fib1 на последнюю позицию (после Fib3)

person Günter Zöchbauer    schedule 07.01.2014
comment
Я не предполагаю, что асинхронность обязательно многопоточная, я программирую на NodeJS, который также имеет однопоточный асинхронный ввод-вывод. И я знаю, что более быстрая программа заканчивается первой. Fib3 на тонны быстрее, чем fib2 и fib1, и он все еще ждет их завершения, а затем все распечатки выполняются синхронно, один за другим, что странно. - person Theofilos Mouratidis; 07.01.2014
comment
Спасибо за разъяснение вашего вопроса. - person Günter Zöchbauer; 07.01.2014
comment
да, я думал о каком-то последовательном выполнении с буферизованным выводом, но это очень странно для того, что вам говорят в документации. Я думал, что Timer.run эквивалентно setTimeout(callback,0) в javascript - person Theofilos Mouratidis; 07.01.2014
comment
Как вы думаете, почему setTimeout (callback, 0) отличается? AFAIK это не - person Günter Zöchbauer; 07.01.2014
comment
напишите эквивалентный код в javascript и выполните его (не dart2js, я запускал сгенерированный код javascript с помощью nodejs, и он сделал то же самое с DartEditor). Вы увидите разные результаты, как и в случае с хромированной консолью. - person Theofilos Mouratidis; 07.01.2014
comment
Я не привык к JS и в моей системе нет NodeJS, так что это слишком большие расходы. Может быть, кто-то еще может предоставить дополнительную информацию. У меня нет объяснения, почему это может вести себя по-другому в JS. То, что я читал о NodeJS, показало, что он работает очень похоже на Dart в отношении асинхронного выполнения. - person Günter Zöchbauer; 07.01.2014
comment
Да, ты прав. Я думал, что асинхронные вызовы псевдопараллельно выполняются в одном потоке - person Theofilos Mouratidis; 07.01.2014