非同期プログラミングには「意識」が必要


私たちは非同期の世界に住んでいますが、多くのプログラミング初心者にとって、非同期はまだよく知られていません.プログラミング言語を学ぶには、通常、同期プロセス、すなわち順序、ブランチ、ループから始まります.非同期プロセスは何ですか.非同期呼び出しを開始し、その後......その後はありません.非同期プログラムはどこへ行きましたか.
非同期プログラムは、処理が完了するまで、マルチスレッド、非同期IOなどの非同期形式で実行されます.結果を処理する必要がある場合はどうすればいいですか?現在のプロセスを処理した後、処理結果をこのエントリに送り、別のプログラム、通称コールバックを実行します.コールバックは一般的にcallbackという名前を使用しますが、次の処理手順を表すため、nextを使用するのが好きな場合があります.
同期と非同期の概念
同期や非同期などの概念に触れました
この2つの概念はプログラミング言語に由来するのではなく、低層命令、さらには低層の回路に由来する.これらはタイミングに基づく2つの概念であり、「ステップ」は歩調を指すので、同期は同じ歩調を表し、非同期は異なる歩調を表す.もちろん、この2つの概念がプログラムのレベルに昇格したとき、正確な意味はクロックとは関係ありませんが、意味は変わりません.
同期
生活の例を挙げてこの問題を説明します.切符を買うことを排除します.切符売り場は窓口が開いていて、並んで順番に切符を買っています.この行列の中で、前の人は一歩前に進んで、後ろの人は一歩前に進むことができます.前の人が待っていて、後ろの人はきっと待っています.理想的には、すべての人が同時に前進することができます.OK、みんなが歩調を合わせて、同期と呼ばれています.
ここでは切符売り場をプロセッサと見なし,一人一人が実行待ちの命令と見なし,切符を買うという動作が命令を実行している.一人で切符を買う時間が長すぎる(命令実行時間が長すぎる)と、渋滞するのが特徴です.
非同期(マルチスレッド)
切符を買う人がだんだん多くなってきたので、切符売り場はいくつかの窓口を開いて同時に切符を売っています.各個別のチームは依然として同期を保っているが、異なるチームの間では、歩調が一致せず、非同期と呼ばれている.A列の切符販売は順調で、列は秩序正しく急速に進んでいるが、B列のある顧客は料金を払う時にトラブルに遭遇したようで、長い時間をかけて渋滞をもたらしたが、これはA列に影響を与えない.
このときのチケット売り場はマルチスレッドで非同期プログラムを実行していると見なすことができる.この例から、非同期の2つの特徴を見ることができます.1つは、2つの非同期プロセス間が互いに独立しており、それらは互いにブロックされません(共有リソースを待つ必要がない前提があります).二つ目は、非同期プログラムの内部は依然として同期されている.
非同期(IO)
上記の例はマルチスレッド非同期の場合に比較的適合する.IO非同期ってどうなの?
年末になって、Mは年末報告の資料を準備しています.これは緊張した仕事です.多くのデータを集めて文案を書く必要があります.その一つの文案のために、Mは職場の生産データを必要とするが、職場(IO)を走るには多くの時間がかかるため、Nに職場に行ってデータを収集させ、自分で他の案を書き続け、Nがデータを収集するのを待つ(非同期プログラムを起動する).半日後、Nはデータを持ち帰って(イベントメッセージを挿入)、Mは手にした文案を完成し続け(現在のイベントループを完成)、その後Nが持ち帰ったデータを使って職場に関するレポートを書き始めた(新しいイベントループ)......
IOの処理速度はCPUよりずっと遅いので、IO非同期でCPUがIO操作の完了を待つ必要がない.IO操作が完了すると、CPUは適宜、IO操作結果を用いて動作を継続する.
同期ロジックと非同期ロジック
プログラムに戻って、同期と非同期の処理方法を関数の処理過程で説明します.
どうきろんり
では、同期処理手順は、次のとおりです.
     ⇒    ⇒     

偽のコードで説明すると
注意:本明細書の擬似コードはJavaScript構文に近いが、タイプを説明するためにType Scriptのタイプを使用して構文を明示する場合がある.
function func(input) {
    do something with input
    return output
}

これは標準的なIPO(Input-Process-Output)処理です.
ひどうきロジック
非同期ですね.
     ⇒    ⇒      (   )

疑似コードで説明すると、
function asyncFunc(input, next) {
    do something with input
    if (next is a entry) {
        next(output)
    }
}

このプロセスをIPN(Input-Process-Next)と呼ぶ.
ここのNextに気づいて、次は、一歩だけ.このステップは、後続のいくつかのステップを網羅しています.したがって、このステップは、後続のいくつかのステップでモジュールエントリ、または関数をカプセル化することしかできません.
そのため、モジュール化思想は非同期思考において非常に重要な思想である.多くの初心者がコードを書くのは流水帳のように一言一句書き下ろすのが好きで、何百行もの関数で、これはモジュール化の思想に欠けている表現です.モジュール化思想には訓練が必要であり,コードの相関性を分析し,関数を抽出し,対象を抽出し,一定の経験を持った後にモジュールの細分化の粒度バランスを把握する必要がある.一朝一夕の功ではありませんが、「デザインモデル」や「再構築」に関する本をお勧めします.
非同期開発ツール(SDKと構文レベル)
承諾(Promise)
以上の年末報告の例を考えてみると、MさんがNさんに職場に行ってデータを収集してもらうと、Nさんは「はい、すぐにデータを持って帰ります」と約束します.この承諾に基づいて、Mは後で職場に関する報告書を書くように手配することができる.このプロセスは擬似コードで記述されています
function collectData(): Promise {
    // N      ,       
    return new Promise(resolve => {
        collect data from workshop
        //            
        resolve(data)
    })
}

function writeWorkshopReport(data) {
    write report with data
}

//            ,           
collectData()
    .then(data => writeWorkshopReport(data))

JavaScriptに代表されるいくつかの言語SDKではPromiseが使用されている.ただし、C#にはTaskTaskが採用されており、Task.ContinueWithの代わりにTask.ContinueWithPromise.thenが使用されている.
非同期論理同期化
同期思考と非同期思考の1つの処理ステップにおける違いについて述べた.1つの処理ステップをスキップすると、より広い範囲の処理フローから見ると、非同期と同期は実際にはそれほど変わらず、 --> --> --> であり、唯一注意しなければならないのは非同期処理によって生成された出力を待つことであり、非同期待機と呼ぶことができる.非同期待機(async wait、略称await)をしながら別のことをすることができるので、この待機はブロックされません.ただし、この待機が宣言されているため、コンパイラ/解釈器は後続のコードを待機完了後に自動的に呼び出し、非同期コードを同期コードを書くように書くことができます.
上記の例では、非同期待機の偽コードを使用すると、このようになります.
async function collectData(): Promise {
    collect data from workshop
    //        async           Promise
    return data
}

function writeWorkshopReport(data) {
    write report with data
}

// await         async     
async function main() {
    data = await collectData()
    writeWorkshopReport(data)
}

//       main   ,       ,         
main()

C#やJavaScriptなどの言語は文法的にawaitasyncと宣言された関数に使用しなければならないことを規定しており、これはコンパイル/解釈の面からawaitの用途を限定しており、awaitを使用すれば、それは非同期コンテキストに違いない.asyncはまた、JavaScriptではPromiseオブジェクトでなければPromiseオブジェクトに自動的にカプセル化されるなど、コンパイラ/解釈器に戻り値の自動処理を要求する.C#では、TaskまたはTaskに自動的にカプセル化されます(したがって、asyncメソッドのタイプはTaskまたはTaskと宣言する必要があります).
気をつける
言語サービスは非同期プログラムの同期化において多くの仕事をしているが、awaitキーワードを書くのを忘れるなどの人為的なエラーは避けられない.強力な言語ではコンパイラは厳しくチェックされますが、JavaScriptではawaitと書くのを忘れたことは、本来値を取るべき文を意味し、Promiseを取得します.解釈器はこれに疑問を抱かないが、プログラムの実行結果は正しくない.
小結
総じて,非同期プログラミングは特に困難なことではない.async/await言語の特性を使用すると、同期コードを記述するような方法で非同期コードを記述することもできます.しかし、文法糖は結局糖であり、非同期プログラミングをよりよく身につけるには、非同期、コールバック、Promise、モジュール化、設計モデル、再構築などの概念を理解し、熟知する必要がある.
関連読書
  • 小さなテーマからJavaScript非同期呼び出し
  • 雑談非同期呼び出し「フラット」化
  • JavaScriptのasync/await
  • を理解する
  • C#並列計算(ParallelとParallelQuery)