Battement. Asynchronie et parallélisme

Bonjour, Habr! Je vous présente la traduction de l' article "Futures - Isolats - Event Loop" de Didier Boelens sur l'asynchronie et le multithreading en Dart(et Flutteren particulier).


TLDR:  ,        .       Event Loop, Future  async/await (,  JavaScript),   otlin,  ,       . ,        .

Et sur la traduction des termes. En langue parléenous Je dis "streams", "trades", "futures", etc., alors qu'en version imprimée ces termes ont l'air étranges et maladroits.


En même temps, c'est Streamun Stream, et Thread- un Stream. Dans ce cas, le contexte n'est pas toujours enregistré. Le même Isolate, à mon goût, sonne normalement en russe, donc quelque part j'utilise l'orthographe en cyrillique, et quelque part dans l'original.


Ici et là entre parenthèses après les mots russes leur original anglais, parfois vice versa.


introduction


Récemment, je reçois souvent des questions relatives aux concepts de Future, async, await, Isolateet exécution en parallèle de code.


De plus, certains développeurs ont du mal à comprendre la séquence d'exécution de leur code.


J'ai décidé de saisir l'occasion et de consacrer un article à ces questions. En même temps, je vais essayer de me débarrasser de la confusion associée principalement aux concepts de et .


Dart - langue Ă  thread unique


, Dart — Flutter Dart.


Dart . . , .

, ( ), , .


void myBigLoop(){
    for (int i = 0; i < 1000000; i++){
        _doSomethingSynchronously();
    }
}

, myBigLoop() . , - , , .


Dart


Dart, , Event Loop.


Flutter- ( Dart-), — Thread, — (Isolate). , .


, :


  1. (Queues) MicroTask ()
    Event (), FIFO (.: first in first out, .. ,
    , ),
  2. main() ,
  3. Event Loop ( )

,
Event Loop
, : MicroTask Event.


Event Loop "" ,
"". ,
Dart-, "" :


void eventLoop(){
    while (microTaskQueue.isNotEmpty){
        fetchFirstMicroTaskFromQueue();
        executeThisMicroTask();
        return;
    }

    if (eventQueue.isNotEmpty){
        fetchFirstEventFromQueue();
        executeThisEventRelatedCode();
    }
}

, MicroTask Event. ?


MicroTask


, , - , Event Loop.


. - , - :


MyResource myResource;

    ...

    void closeAndRelease() {
        scheduleMicroTask(_dispose);
        _close();
    }

    void _close(){
        // ,     
        //   
        ...
    }

    void _dispose(){
        // ,    
        //   ,  _close()
        // 
    }

-, , . , scheduleMicroTask() 7 . Event.


Event


, :


  • ,
    • /
    • ...
  • Future

, , Event.


, MicroTask , Event Loop Event .


, Futures Event.


Futures


Future , ( ) - .


, Future:


  • , Dart
  • , Future,
    Event
  • Future (incomplete)
  • , ( Future)

, Future Event,
Event Loop .


( ) then()
catchError() Future.


, :


void main(){
    print('Before the Future');
    Future((){
        print('Running the Future');
    }).then((_){
        print('Future is complete');
    });
    print('After the Future');
}

, :


Before the Future
After the Future
Running the Future
Future is complete

:


  1. print('Before the Future')
  2. (){print('Running the Future');} Event
  3. print('After the Future')
  4. Event Loop 2
  5. , then()

:


Future , , Event Loop

(async)


async, Dart , :


  • — Future
  • , await,
  • Future, await

, await , [ Future], .
Event Loop...


,
,


void main() async {
  methodA();
  await methodB();
  await methodC('main');
  methodD();
}

methodA(){
  print('A');
}

methodB() async {
  print('B start');
  await methodC('B');
  print('B end');
}

methodC(String from) async {
  print('C start from $from');

  Future((){                // <==     -  
    print('C running Future from $from');
  }).then((_){
    print('C end of Future from $from');
  });

  print('C end from $from');  
}

methodD(){
  print('D');
}

:


A
B start
C start from B
C end from B
B end
C start from main
C end from main
D
C running Future from B
C end of Future from B
C running Future from main
C end of Future from main

, methodC() . , , .


, methodD() , :


void main() async {
  methodA();
  await methodB();
  await methodC('main');
  methodD();  
}

methodA(){
  print('A');
}

methodB() async {
  print('B start');
  await methodC('B');
  print('B end');
}

methodC(String from) async {
  print('C start from $from');

  await Future((){                  // <==  
    print('C running Future from $from');
  }).then((_){
    print('C end of Future from $from');
  });
  print('C end from $from');  
}

methodD(){
  print('D');
}

:


A
B start
C start from B
C running Future from B
C end of Future from B
C end from B
B end
C start from main
C running Future from main
C end of Future from main
C end from main
D

, await Future methodC() .


:


, , Event Loop

. . method1 — method2? ?


void method1(){
  List<String> myArray = <String>['a','b','c'];
  print('before loop');
  myArray.forEach((String value) async {
    await delayedPrint(value);
  });  
  print('end of loop');
}

void method2() async {
  List<String> myArray = <String>['a','b','c'];
  print('before loop');
  for(int i=0; i<myArray.length; i++) {
    await delayedPrint(myArray[i]);
  }
  print('end of loop');
}

Future<void> delayedPrint(String value) async {
  await Future.delayed(Duration(seconds: 1));
  print('delayedPrint: $value');
}

: .


, method1 forEach() . , async ( Future). await, Event. , : print('end of loop'). Event Loop 3 .


method2, ( ) — .


, ,
Event Loop...



, Flutter? ?


, Isolate ().



, Isolate Dart Thread ().


Thread.


Flutter . .

Event Loop.


(MicroTask Event).


.


Dart.



, .


1.


() API, Dart.


1.1. 1:


, , , "" "" .


, , . SendPort ( , , /, ).


, "" " " , "". :


//
//   
//     
//    
//
SendPort newIsolateSendPort;

//
//   
//
Isolate newIsolate;

//
// ,    
//   
//
void callerCreateIsolate() async {
    //
    //   ReceivePort  
    // SendPort  
    //
    ReceivePort receivePort = ReceivePort();

    //
    //   
    //
    newIsolate = await Isolate.spawn(
        callbackFunction,
        receivePort.sendPort,
    );

    //
    //     ""
    //
    newIsolateSendPort = await receivePort.first;
}

//
//    
//
static void callbackFunction(SendPort callerSendPort){
    //
    //   SendPort   
    //  ""
    //
    ReceivePort newIsolateReceivePort = ReceivePort();

    //
    //  ""   SendPort  
    //
    callerSendPort.send(newIsolateReceivePort.sendPort);

    //
    //  
    //
}

:

1.2. 2:


, , :


//
// ,     
//   
// 
//     ""
//   String (   )
//
Future<String> sendReceive(String messageToBeSent) async {
    //
    //     
    //
    ReceivePort port = ReceivePort();

    //
    //   ,  
    //  ,   
    //   
    //
    newIsolateSendPort.send(
        CrossIsolatesMessage<String>(
            sender: port.sendPort,
            message: messageToBeSent,
        )
    );

    //
    //     
    //
    return port.first;
}

//
// Callback-    
//
static void callbackFunction(SendPort callerSendPort){
    //
    //   SendPort   
    //  
    //
    ReceivePort newIsolateReceivePort = ReceivePort();

    //
    //  ""   SendPort  
    //
    callerSendPort.send(newIsolateReceivePort.sendPort);

    //
    //  ,    ,
    //    
    //
    newIsolateReceivePort.listen((dynamic message){
        CrossIsolatesMessage incomingMessage = message as CrossIsolatesMessage;

        //
        //  
        //
        String newMessage = "complemented string " + incomingMessage.message;

        //
        //   
        //
        incomingMessage.sender.send(newMessage);
    });
}

//
//  
//
class CrossIsolatesMessage<T> {
    final SendPort sender;
    final T message;

    CrossIsolatesMessage({
        @required this.sender,
        this.message,
    });
}

1.3. 3:


, :


void dispose(){
    newIsolate?.kill(priority: Isolate.immediate);
    newIsolate = null;
}

1.4. — Stream


, "" "" (Streams). Single-Listener Stream ( ).


2. (One-shot computation)


, , Dart compute,


  • ,
  • — -
  • .

: ( ).

3.


, ,


(Platform-Channel communication) (main isolate). , .

, ,
.


Future


, :


  • (user friendliness)

, (user experiences lags), .


, :


  1. ,
    ( )
  2. ,
    , — Event Loop Futures
  3. ,
    , —

, , , Futures ( async-) — Futures Event Loop "" . , ( - , ).


, Future — , .


  • => Future
  • =>

:


  • JSON, (HttpRequest),
    => compute
  • : =>
  • ( ..) =>
  • : , , .


, , Event Loop .


Il est également important de ne pas oublier que Flutter( Dart) est monothread, donc pour satisfaire les utilisateurs, les développeurs doivent être sûrs que l'application fonctionnera aussi bien que possible. Futureset - des outils puissants pour aider à atteindre cet objectif.


Bonne chance


All Articles