Aleteo. Asincronía (asincrónica) <> paralelismo (aislar). En absoluto

Introducción



Recientemente, me sorprendió descubrir que mis colegas no tienen total claridad sobre qué es la asincronía en Flutter. Por alguna razón, tuvieron la idea de que si la función asincrónica está escrita correctamente, entonces no bloquea la interfaz. Después de haber examinado un par de artículos, no encontré una explicación simple, completa y clara de toda esta cocina (todo está de acuerdo con el principio - "elige 2 de 3")). En un artículo incluso leí que Dart tiene una asincronía maravillosa, que le permite posponer la ejecución del código hasta que el hilo sea más libre (lo que en mi opinión es un poco engañoso) (Nota: en los comentarios nikita_dolseñaló lo que probablemente significaba - scheduleTask ).



Para quien el articulo



El artículo está destinado a aquellos que recién comienzan a familiarizarse con Flutter, por lo que intentaré mostrar con un ejemplo simple en esta pequeña nota que la asincronía es solo la capacidad de ejecutar código no secuencialmente. Pero, si tiene una función "pesada" (incluso si es tres veces asíncrona), seguirá bloqueando la interfaz por usted. Por supuesto, en un producto real, es poco probable que encuentre manifestaciones tan obvias (por el momento, los procesadores son bastante poderosos), pero aún así vale la pena comprender cómo funciona.



Vamos



Entonces, tomemos un ejemplo de la documentación de la biblioteca flutter_bloc para experimentos . Modifiquemos ligeramente la función "_mapTimerStartedToState" de la clase timer_bloc - comente la actualización del contador para que no interfiera:



Stream<TimerState> _mapTimerStartedToState(TimerStarted start) async* {
  yield TimerRunInProgress(start.duration);
  _tickerSubscription?.cancel();
  // _tickerSubscription = _ticker
  //     .tick(ticks: start.duration)
  //     .listen((duration) => add(TimerTicked(duration: duration)));
}

      
      







Agreguemos una nueva función estática (la hacemos así de antemano; aislar funciona solo con ellos) función:



static Future<void> _heavyComput (SendPort sendPort) async {
  await Future.delayed(Duration(seconds: 5));

  print('=======================');
  print('!!!function finished!!!');
  print('=======================');
  return null;
}

      
      







Aquí, como una emulación de cálculos pesados, estamos esperando el final del retraso de 5 segundos.

Modificamos la función mapEventToState: agregamos una llamada asincrónica a _heavyComput al final:



@override
Stream<TimerState> mapEventToState(
  TimerEvent event,
) async* {

. . .
  
  _heavyComput(null);
}

      
      







Para la primera prueba, todo está listo: nuestra tarea es observar las ondas mágicas.

Lanzamos y vemos: las ondas están preocupadas, la interfaz no está bloqueada, el mensaje sobre el final de la función se muestra después de 5 segundos.







Esta es una asincronía maravillosa: el pánico era falso. Hmm ... ¿Qué pasa si Future.delayed (Duration (segundos: 5)) se reemplaza con un bucle?



static Future<void> _heavyComput(SendPort sendPort) async {
  int pause = 1200000000;
  for (int i = 0; i < pause; i++) {}
  print('=======================');
  print('!!!function finished!!!');
  print('=======================');
  return null;
}

      
      





Lo lanzamos y listo - "llegó" - las olas ya no preocupan.







No creo que se necesite mucha explicación aquí: incluso una función pesada asincrónica bloquea todo. De forma predeterminada, todo el código se ejecuta en un hilo. Es solo que en el primer caso, no se requirieron cálculos, pero solo hubo que esperar, y en el segundo, se necesitaron cálculos.



Bueno, y para que el artículo no resulte completamente microscópico, llamemos a esta función usando aislar. Cambiemos el mapEventToState:



@override
Stream<TimerState> mapEventToState(
  TimerEvent event,
) async* {
. . .
  var _receivePort = ReceivePort();
  var _isolate = Isolate.spawn(_heavyComput, _receivePort.sendPort);
}

      
      







Lo iniciamos y vemos que la interfaz no está bloqueada, recibimos un mensaje sobre la finalización de la función con un retraso notable.







Eso es todo (cómo funcionan async y await; hay muchos artículos, creo que no deberías detenerte allí).



Se puede descargar un ejemplo desde el enlace: flutter_timer_async_and_parallels



All Articles