C# の async/await

非同期実行(別スレッドで実行)する処理と、その処理の完了後に実行される処理を、同期実行に似たかたちのコードで書くためのキーワード。
asyncは、内部でawaitを使う関数であることを示すためのキーワードで、機能は無い。
awaitは、その直後に「Taskオブジェクトを戻す式」を置く。
「Taskオブジェクトを戻す式」が実行された時点でasync関数の動作は一時ストップする。「Taskオブジェクトを戻す式」のTaskの処理が完了したら、async関数の動作が再開する。

private async void AsyncRun()
{
    MessageBox.Show("start");
    foreach (var i in Enumerable.Range(0, 5))
    {
        await Task.Delay(1000);   // Task.Run(() => System.Threading.Thread.Sleep(1000)) と同じ
        MessageBox.Show(i.ToString());
    }
    MessageBox.Show("end");
}

asyncキーワードの書かれた関数f は ジェネレータを返すyield関数 になり、await直後の式のpromeseを戻して、promise.thenでfを継続実行させる。
(await x → yield x.then(arguments.callee()).resolve() に展開)
という感じで理解できる概念。



javascript(ES2016)にもほぼ完全に同じ機能がある。
ただしawaitの後に続く関数はTaskではなくpromiseを戻すべきであるところが違う。
http://www.atmarkit.co.jp/ait/articles/1601/22/news038_2.html

function doLongTimeTask(n, msg) {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve('resolved: ' + msg), n);
  });
}

async function doLongTimeTaskAsync() {
  var result;
  result = await doLongTimeTask(1000, 'task1');
  console.log(result);
  result = await doLongTimeTask(1000, 'task2');
  console.log(result);
  result = await doLongTimeTask(1000, 'task3');
  console.log(result);
}