C# 5の非同期、パート1
2019-03-22 09:37:19
C# 2.0のデザイナーは、イテレーターロジックを書くのはつらいと気づいた。そこで彼らはイテレーターブロックを追加した。こうして、コンパイラは継続――「次に来るもの」――をどこかの状態に、舞台裏に隠しながら保存できるステート・マシンを構築する方法がわかるようになり、あなたがコードを書く必要はなくなった。
彼らはまた、ローカル変数を利用する小さなメソッドを書くこともつらいと気づいた。それで彼らは匿名メソッドを追加した。こうして、コンパイラはクロージャ・クラスにローカル変数を渡す方法がわかるようになり、あなたがコードを書く必要はなくなった。
C# 3.0のデザイナーは、複雑なデータセットをソートして、フィルタリングして、結合して、グループ化して、集約するコードを書くのはつらいと気づいた。そこで彼らはクエリ内包とその他すべてのLINQ機能を追加した。こうしてコンパイラはクエリや式木などを構築するために適切なオブジェクトモデル呼び出しを実行する方法がわかるようになった。
C# 4.0のデザイナーは、レガシーな動的オブジェクト・モデルと最新のものとを相互運用するのはつらいと気づいた。そこで彼らはdynamic型を追加した。こうして、コンパイラは実行時にDynamic Language Runtimeで分析するコードをコンパイル時に生成する方法がわかるようになった。
C# 5.0のデザイナーは、非同期コードを書くのはとても多くの点でつらいと気づいた。非同期コードは推論するのが難しく、すでに見たように継続への変換は複雑で、コードの意味を不明瞭にするメカニズムでコードがいっぱいになる。
これを我慢してはいけない。
C# 5.01 をお知らせしよう。C# 5.0では、次の同期コードを元に:
void ArchiveDocuments(List<Url> urls)
{
for(int i = 0; i < urls.Count; ++i)
Archive(Fetch(urls[i]));
}
そして、FetchAsync
とArchiveAsync
メソッドの合理的な実装があれば、昨日説明したように、次のコードに変換して、待ち時間を共有するというゴールを達成することができる:
async void ArchiveDocuments(List<Url> urls)
{
Task archive = null;
for(int i = 0; i < urls.Count; ++i)
{
var document = await FetchAsync(urls[i]);
if (archive != null)
await archive;
archive = ArchiveAsync(document);
}
}
いったいどこに、ステート・マシンのコードや、ラムダや、継続や、タスクがすでに完了しているかどうかの確認があるのか?それらはすべて、まだそこにある。イテレータブロックや、クロージャや、式木や、クエリ内包や、ダイナミックな呼び出しのコードをコンパイラに生成させたのと同じように、それら全てをコンパイラに生み出させよう。 上のC# 5.0コードは、基本的に、昨日説明したコードの構文糖だ。相当甘い砂糖だけれど!
次のことについてはっきりさせておきたい: 上のコードの動作は、昨日のコードの動作と論理的に同じだ。 タスクが「await(待期)」しているときはいつも、現在のメソッドの残りはタスクの継続として登録され、そして制御は直ちに呼び出し側に戻る。タスクが完了すると、継続が呼び出され、メソッドは以前の場所から起動する。
私がこの記事を投稿する時間を正しく設定できていたなら、ちょうど……今頃、AndersはPDCでこの新しい言語機能を発表している。それはここで見ることができる。
我々は、ちょうど今、プロトタイプC# 5.0コンパイラのCommunity Technology Preview版を利用できるようにしている。プロトタイプ・コンパイラは、プロトタイプ品質だ;機能はまだ不安定でラフであると思っていてほしい。狙いは、試す機会を与えて、それについて何を考えているかを知ることで、我々が早期のフィードバックを得ることができるようにすることだ。
私は明日、そしてその後しばらくして、この機能についてもっと多く投稿するつもりだ;それまで待てないか、プロトタイプを手にしたいなら、 http://msdn.com/vstudio/async から多くの詳細な情報と、新しくておいしいコンパイラのバイナリを入手できる。
そしてもちろん、我々の共進化戦略に合わせてVisual Basic 11も予定されており、そちらもタスク・ベースの非同期をフィーチャーしたものになるだろう。詳細についてはVBチームのブログをチェックするか、私の同僚であるLucianのブログでこの機能について読むこと。(Lucianは、C#とVBの両方で、この機能のデザインとプロトタイピングに多くかかわっている;この件の専門家は私ではなく彼なので、深い質問をしたいなら、私でなく彼に質問するといい。)
明日: await
? async
? Task
? AsyncThingy<T>
はどうなった?もっと教えろ!
-
今の時点で我々は日付や出荷手段を少しも全く明らかに発表していない。だから質問したりしないこと。たとえ私が知っていたとしても、とは言っても私は知らないし、そしてたとえその知識が正確である可能性がかすかにあったとしても、とは言ってもその可能性はないのだが、私はまだあなた達に教えられない。 ↩︎