非同期処理(async,await,Future)について

2024/06/20に公開

同期処理について

同期処理とは、ひとつの処置が終わるまで次の処理が開始されない方式。
例では、task2で3秒待たせてから処理が行われている。

main.dart
import 'dart:async';
import 'dart:io';

void main() { 
  multitask();
// task1 complete
// task2 complete ← 3秒待ってから表示
// task3 complete ← task2の処理を待ってから表示
}

void multitask () {
  task1();
  task2();
  task3();
}

void task1 () {
  print("task1 complete");
}

void task2() {
  Duration threeSeconds = Duration(seconds: 3);
  sleep(threeSeconds);// ← 3秒経つまで全ての処理を止める。
  print("task2 complete");
}

void task3 () {
  print("task3 complete");
}

非同期処理

処理の実行中だとしても、違う処理もバックグラウンドで同時に行える方式。
同期処理は、どんなに時間がかかっても実行中の処理を待たないと次の処理に移れないため
効率が悪い。
例では、futureメソッドを使って非同期処理をシュミレーションしている。
task2を3秒待たせてる間にtask3の処理を行なっている。

main.dart
import 'dart:async';

void main() {
// task1 complete
// task3 complete
// task2 complete
  multitask();
}

void multitask () {
  task1();
  task2();
  task3();
}

void task1 () {
  print("task1 complete");
}

void task2() {
  Duration threeSeconds = Duration(seconds: 3);

  Future.delayed(threeSeconds,() {
   print("task2 complete"); 
  });
}

void task3 () {
  print("task3 complete");
}

Futureクラスについて

Futureクラスは、非同期処理の結果として、uncompleted(未完了)とcompleted(完了)のふたつの状態を持つことができる。

  • uncompleted(未完了)
    未完了のFutureインスタンスを返す。
  • completed(完了)
    非同期処理が成功した場合、futureは値で返す。
main.dart
import 'dart:async';

void main() { 
  // task1 complete
  // ▼Futureの処理が終わっていないため、インスタンスそのものが返ってくる。
  // Instance of 'Future<String?>' 
  // ▼Futureの処理が完了して値が返ってくる。
  // task2 complete at: 2024-06-20 04:23:32.383102
  multitask();
}

void multitask () {
  task1();
  print(task2());
}

void task1 () {
  print("task1 complete");
}

Future<String?> task2() async {
  Duration threeSeconds = Duration(seconds: 3);

   return await Future.delayed(threeSeconds,() {
   print("task2 complete at: ${DateTime.now()}"); 
  });
}

async,await

async,awaitは、非同期処理を宣言し定義するもの。
task1~3の関数だけで見ると、同期処理をしているように見えるが、
Timer関数を記述することでtask2の処理中も、他の処理を受け付けていることが分かる。

main.dart
import 'dart:async';

void main() {
  // task1 complete
  // Waiting... 2024-06-20 02:25:18.298434
  // Waiting... 2024-06-20 02:25:19.294962
  // Waiting... 2024-06-20 02:25:20.294969
  // task2 complete at: 2024-06-20 02:25:20.296256
  // task3 complete task2 data
  multitask();
}

void multitask () async {
  task1();
  // task2処理中も違う処理を行えるはず...
  Timer.periodic(Duration(seconds: 1), (timer) {
    print('Waiting... ${DateTime.now()}');
  });
  String? task2result = await task2();
  task3(task2result);
}

void task1 () {
  print("task1 complete");
}

Future<String?> task2() async {
  Duration threeSeconds = Duration(seconds: 3);
  String? result;
  
  await Future.delayed(threeSeconds,() {
   result = "task2 data";
   print("task2 complete at: ${DateTime.now()}"); 
  });
  
  return result;
}

void task3 (String? task2result) {
  print("task3 complete $task2result");
}

非同期処理の用途

  • ネットワーク経由でデータを取得する。
  • データベースへの書き込み
  • ファイルからデータを読み込む

Discussion