第3章 非同期ストリーム 非同期ストリーム
この作品はAIを使って翻訳されている。ご意見、ご感想をお待ちしている:translation-feedback@oreilly.com
非同期ストリームは、 複数のデータ・アイテムを非同期に受信する方法である。これは非同期列挙型(IAsyncEnumerable<T> )をベースにしている。非同期列挙型は、列挙型の非同期バージョンである。つまり、列挙型は、コンシューマに対してオンデマンドでアイテムを生成することができ、各アイテムは非同期に生成することができる。
非同期ストリームを、より馴染みのある他の型と対比させ、その違いを検討することは有益だと私は発見した。これは、非同期ストリームを使うべき時と、他のタイプがより適切な時を思い出すのに役立つ。
非同期ストリームと Task<T>
Task<T> を使った標準の非同期アプローチは、単一のデータ値を非同期に処理するのに十分なだけである。与えられたTask<T> が完了したら、それで終わりである。単一のTask<T> は、そのコンシューマにT の複数の値を提供することはできない。たとえT がコレクションであっても、値は一度しか提供できない。async とTask<T> の使い分けについては、「非同期プログラミング入門」と第2章を参照のこと。
Task<T> と非同期ストリームを比較すると、非同期ストリームの方が列挙型に近い。具体的には、IAsyncEnumerator<T> は、任意の数のT 値を、一度に1つずつ提供することができる。IEnumerator<T> のように、IAsyncEnumerator<T> は無限長になる可能性がある。
非同期ストリームと IEnumerable<T>
IAsyncEnumerable<T> IEnumerable<T>どちらもコンシューマが要素を1つずつ取り出すことができる。大きな違いは名前にある。一方は非同期で、もう一方は非同期ではない。
コードがIEnumerable<T> を反復処理する場合、列挙可能要素から各要素を取得するときにブロックされる。IEnumerable<T> がデータベースのクエリやAPI呼び出しのようなI/Oバウンド操作を表している場合、消費するコードはI/Oでブロックすることになり、これは理想的なことではない。IAsyncEnumerable<T> は、次の各要素を非同期に取得することを除いて、IEnumerable<T> と同じように動作する。
非同期ストリームとタスク<IEnumerable<T>>について
複数のアイテムを持つコレクションを非同期に返すことは、完全に可能である。よくある例としては、Task<List<T>> がある。それでも、List<T> を返すasync メソッドは、return の文を1つしか受け取らない。コレクションが返される前に、コレクションが完全に生成されていなければならない。Task<IEnumerable<T>> を返すメソッドでも、非同期に列挙型を返すことがあるが、その場合、列挙型は同期的に評価される。LINQ-to-Entitiesには、Task<List<T>> を返すToListAsync LINQメソッドがあるとする。LINQプロバイダがこのメソッドを実行すると、データベースと通信し、一致するすべてのレスポンスを取得してから、リストの入力を終えてそれを返す必要がある。
Task<IEnumerable<T>> コレクションを返す場合、すべての項目をメモリにロードし、コレクションに入力し、コレクション全体を一度に返さなければならない。LINQクエリを返す場合でも、非同期にクエリを構築することができるが、クエリが返されると、各項目はそのクエリから同期的に取得される。 ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access