非同期処理

非同期処理

執筆済 ソフトウェア開発

待ち時間の間に他の仕事をする。

I/O(ネットワーク、ディスク)は CPU より 5〜6 桁遅い。 待っている間 UI を止めると、アプリが固まる。

表現の変遷#

形式 問題
コールバック ネストが深くなる。エラー処理が散らばる
Promise / Future 連結できる。まだ手続き的でない
async / await 同期コードのように書ける
リアクティブ (Rx, Combine) ストリームとして扱う。学習コストが高い
// コールバック
fetch(url, { data in parse(data, { result in show(result) }) })

// async/await
let data = try await fetch(url)
let result = try parse(data)
show(result)

関数の色#

async な関数は async な文脈からしか呼べない。 この制約が呼び出し側へ伝播していく(関数の色問題)。

同期コードから非同期を呼ぶには 境界(TaskPromise の生成)が要る。 軽量スレッド方式 (Go、Java 仮想スレッド)はこの問題を回避している。

並行実行#

逐次: await a(); await b()      … a が終わってから b
並行: async let x = a(); async let y = b(); await (x, y)

独立した処理を逐次で待つのは無駄。 3 つの API を順に待つと 3 倍の時間がかかる。

中断とキャンセル#

画面を閉じたのに通信が続くのは資源の無駄。

  • Swift の構造化並行性 — 親タスクの終了で子も取り消される
  • AbortController(Web)

開始したものを取り消せる設計にしておく。

参考文献#

ノート一覧を閉じる