Thomas Ecalle
Développeur mobile Android natif depuis 3 ans
Développeur Flutter passionné depuis 1an
Mail : thomasecalle@gmail.com
Github : https://github.com/ThomasEcalle
Linkedin: https://www.linkedin.com/in/thomas-ecalle-239568120/
Medium: https://medium.com/@thomas_49096
Cyllene - Multithreading en Flutter
Asynchronisme vs Parallélisme vs Concurrence
Comment le langage Dart fonctionne ?
Penchons-nous sur les Futures
Le vrai Multithreading : les Isolate
Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
Définition Wikipédia :
asynchrony, in computer programming, refers to the occurence of events independent of the main program flow and ways to deal with such events.
Cyllene - Multithreading en Flutter
Parallel computing is a type of computation in which many calculations or the execution of processes are carried out simultaneously. Large problems can often be divided into smaller ones, which can then be solved at the same time.
Définition Wikipédia :
Cyllene - Multithreading en Flutter
Concurrent computing is a form of computing in which several computations are executing during overlapping time periods - concurrently - instead of sequentially (one completing before the next starts).
Définition Wikipédia :
Cyllene - Multithreading en Flutter
C'est une question de point de vue
Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
Un seul Thread (Isolate) créé au démarrage de l’application
Dart n’exécute qu’une instruction à la fois
BLOQUANT
void myBigLoop(){
for (int i = 0; i < 1000000; i++){
_doSomethingSynchronously();
}
}Cyllene - Multithreading en Flutter
- I/0
- Gestures
- Streams
- ...
- Futures
Cyllene - Multithreading en Flutter
L'Event Loop est une boucle infinie qui check régulièrement si une opération I/O doit être exécutée ou est terminée
Cyllene - Multithreading en Flutter
Ce n'est donc pas de la vraie concurrence
Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
void main() {
Future(() {
return 42;
}).then((value) {
print("Value: $value");
}).catchError((error) {
print("Error: $error");
});
}Cyllene - Multithreading en Flutter
void main() {
_getIntFromNetwork().then((int value) {
print("Got value: $value");
}).catchError((error) {
print("Got an error: $error");
});
}
Future<int> _getIntFromNetwork() async {
await Future.delayed(Duration(seconds: 2));
return 42;
}Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
void main(){
print('1');
Future((){
print('2');
}).then((_){
print('3');
});
print('4');
}Cyllene - Multithreading en Flutter
1
4
2
3Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
void main() {
print("1");
Future(() {
print("2");
}).then((value) {
print("3");
}).catchError((error) {
print("Error: $error");
});
for (int i = 0; i < 10000000; i++) {
print("ok $i");
}
}Ici, la boucle s'effectuera toujours avant les prints 2 et 3
Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
void main() {
print("1");
Future(() {
print("2");
}).then((_) {
print("3");
});
}void main() async {
print("1");
await Future(() {
print("2");
});
print("3");
}Ces deux codes sont strictement équivalents :
Cyllene - Multithreading en Flutter
async / await ne change RIEN au séquençage habituel et à l'Event Loop
Cyllene - Multithreading en Flutter
Qu'affichent ces différents programmes ?
Pourquoi ?
Cyllene - Multithreading en Flutter
void main() async {
await a();
await b();
}
Future<void> a() async {
await Future.delayed(Duration(seconds: 1));
print("A");
}
Future<void> b() async {
print("B start");
await c();
print("B end");
}
Future<void> c() async {
print("C start");
Future(() => print("C Middle")).then((_) => print("C Middle End"));
print("C end");
}Cyllene - Multithreading en Flutter
void main() {
final List<String> list = ["Flutter", "is", "awesome"];
a(list);
b(list);
}
void a(List<String> list) async {
print("Before loop A");
list.forEach((String value) async {
await delayedPrint(value);
});
print("After loop A");
}
void b(List<String> list) async {
print("Before loop B");
for (int index = 0; index < list.length; index++) {
await delayedPrint(list[index]);
}
print("After loop B");
}
Future<void> delayedPrint(String value) async {
await Future.delayed(Duration(seconds: 1));
print(value);
}Cyllene - Multithreading en Flutter
| a() | b() |
|---|---|
| Before loop A | Before loop B |
| After loop | Flutter (après 1 seconde) |
| Flutter (après 1 seconde) | is (après 1 seconde) |
| is (tout de suite après) | awesome (après une seconde) |
| awesome (tout de suite après) | After loop B (tout de suite après) |
Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
void a(List<String> list) async {
print("Before loop A");
await Future.forEach(list, (String el) async {
await delayedPrint(el);
});
print("After loop A");
}Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
Chaque isolate aura :
Cyllene - Multithreading en Flutter
Avantages :
Inconvénients :
Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
Les boutons vont tous les deux lancer ce "gros" calcul :
int bigTask(num n) {
int result = 0;
for (int i = 0; i < n; i++) {
result += i;
}
return result;
}Cyllene - Multithreading en Flutter
Tout d'abord, en utilisant une Future :
_runOnMainThread(BuildContext context) {
Future<int>(() {
return bigTask(NB_ITERATIONS);
}).then((int value) {
_showSnackBar(context, value);
});
}Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
Utilisons un Isolate séparé !
Transformer notre code pour utiliser un Isolate va-t-il être un processus :
L'UI freeze car la Future n'est pas réellement jouée en parallèle...
?
Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
Nous allons utiliser la manière la plus simple :
La méthode compute provenant de flutter/foundation.dart
Voici la méthode utilisant un Isolate séparé :
_runOnSecondIsolate(BuildContext context) async {
final int result = await compute(bigTask, NB_ITERATIONS);
_showSnackBar(context, result);
}Cyllene - Multithreading en Flutter
Donc :
static int bigTask(num n) {
int result = 0;
for (int i = 0; i < n; i++) {
result += i;
}
return result;
}Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
La méthode compute nous a permis de :
Finalement nous avons :
Cyllene - Multithreading en Flutter
La méthode compute peut prendre "du temps" à créer et lancer l'Isolate
Il arrive donc que ce ne soit pas la solution optimale
Cyllene - Multithreading en Flutter
Selon le temps que prendra à priori votre tâche :
Cyllene - Multithreading en Flutter
Nous avons utilisé la manière la plus haut niveau et simple pour créer et utiliser un Isolate
Il est bien sûr possible d'avoir plus de contrôle sur l'Isolate et s'échanger des messages entre Main Isolate et Isolates tiers
Cyllene - Multithreading en Flutter
Isolate isolate;
void start() async {
final ReceivePort receivePort = ReceivePort();
isolate = await Isolate.spawn(task, receivePort.sendPort);
receivePort.listen((data) {
print('RECEIVE: ' + data + ', ');
});
}
void task(SendPort sendPort) {
int counter = 0;
Timer.periodic(Duration(seconds: 1), (Timer t) {
counter++;
sendPort.send("Counter value = $counter");
});
}
void stop() {
if (isolate != null) {
isolate.kill(priority: Isolate.immediate);
isolate = null;
}
}
void main() async {
await start();
await stdin.first;
stop();
print("Stopped processus");
exit(0);
}Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
Pour une bonne UI et donc une bonne application, il est primordial de :
Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
thomasecalle@gmail.com
Linkedin : https://www.linkedin.com/in/thomas-ecalle-239568120/
Github : https://github.com/ThomasEcalle
Medium: https://medium.com/@thomas_49096
Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
Cyllene - Multithreading en Flutter
Répondre sur : https://meetup-paris-isolates.firebaseapp.com
void main() async {
print("1");
await a();
print("7");
}
Future<void> a() async {
print("2");
Future(() => print("3")).then((_) {
throw Exception();
print("4");
}).catchError((error) {
print("5");
});
print("6");
}Cyllene - Multithreading en Flutter