非同期プログラミングの概要
IAsyncResult デザイン パターンを使用する非同期操作は、BeginOperationName および EndOperationName という名前の 2 つのメソッドとして実装されます。これらは、非同期操作 OperationName をそれぞれ開始および終了するものです。たとえば、FileStream クラスは、BeginRead および EndRead メソッドを提供して、非同期的にファイルからバイトを読み取ります。これらのメソッドは、非同期バージョンの Read メソッドを実装します。
BeginOperationName を呼び出した後、アプリケーションは、別のスレッドで非同期操作が行われている間も、呼び出し元スレッドで命令の実行を続行できます。BeginOperationName を呼び出すたびに、アプリケーションは EndOperationName も呼び出して、操作の結果を取得する必要があります。
非同期操作の開始
BeginOperationName メソッドは、非同期操作 OperationName を開始し、IAsyncResult インターフェイスを実装するオブジェクトを返します。IAsyncResult オブジェクトは、非同期操作に関する情報を保存します。非同期操作に関する情報を次の表に示します。
メンバ | 説明 |
---|---|
オプションのアプリケーション固有のオブジェクト。非同期操作に関する情報を含みます。 |
|
WaitHandle。非同期操作が完了するまで、アプリケーションの実行をブロックするのに使用できます。 |
|
個々の ThreadPool スレッドで完了したかどうかではなく、BeginOperationName の呼び出しに使用されたスレッド上で非同期操作が完了したかどうかを示す値。 |
|
非同期操作が完了したかどうかを示す値。 |
BeginOperationName メソッドは、値または参照によって渡された、同期バージョンのメソッドのシグネチャで宣言された任意のパラメータを受け取ります。out パラメータは、BeginOperationName メソッド シグネチャの一部ではありません。BeginOperationName メソッド シグネチャにも、2 つの追加のパラメータが含まれます。1 つ目のパラメータは、非同期操作が完了したときに呼び出されるメソッドを参照する AsyncCallback デリゲートを定義します。操作完了時にメソッドを呼び出さない場合、呼び出し元は null (Visual Basic では Nothing) を指定できます。2 つ目の追加のパラメータは、ユーザー定義オブジェクトです。このオブジェクトを使用すると、アプリケーション固有の状態情報を、非同期操作が完了したときに呼び出されたメソッドに渡すことができます。BeginOperationName メソッドが、追加の操作固有のパラメータ (ファイルから読み取ったバイトを保存するバイト配列など) を受け取る場合、AsyncCallback およびアプリケーション状態オブジェクトが、BeginOperationName メソッド シグネチャ内の最後のパラメータになります。
Begin OperationName は、呼び出し元スレッドに即座に制御を戻します。BeginOperationName メソッドが例外をスローする場合、例外は非同期操作が開始される前にスローされます。BeginOperationName メソッドが例外をスローする場合、コールバック メソッドは呼び出されません。
非同期操作の終了
EndOperationName メソッドは、非同期操作 OperationName を終了します。EndOperationName メソッドの戻り値は、対応する同期で戻されるものと同じ型であり、非同期操作に固有です。たとえば、EndRead メソッドは FileStream から呼び取ったバイト数を返し、EndGetHostByName メソッドはホスト コンピュータに関する情報を含む IPHostEntry オブジェクトを返します。EndOperationName メソッドは、同期バージョンのメソッドのシグネチャで宣言された任意の out または ref パラメータを受け取ります。EndOperationName メソッドは、同期メソッドから受け取ったパラメータだけでなく、IAsyncResult パラメータも含みます。呼び出し元は、BeginOperationName への対応する呼び出しによって返されたインスタンスを渡す必要があります。
IAsyncResult オブジェクトによって表される非同期操作が、EndOperationName の呼び出し時にまだ完了していない場合、EndOperationName は非同期操作が完了するまで呼び出し元スレッドをブロックします。非同期操作によってスローされた例外は、EndOperationName メソッドからスローされます。同じ IAsyncResult で EndOperationName メソッドを複数回呼び出す効果は定義されていません。同様に、関連する Begin メソッドによって返されたのではない IAsyncResult で、EndOperationName メソッドを呼び出すことも定義されていません。
メモ : |
---|
いずれの未定義のシナリオでも、実装の際には InvalidOperationException のスローを検討する必要があります。 |
メモ : |
---|
このデザイン パターンを実装した場合は、呼び出し元に非同期操作が完了したことを通知する必要があります。IsCompleted を true に設定し、非同期コールバック メソッドを呼び出し (1 つも指定されていない場合)、AsyncWaitHandle を通知します。 |
アプリケーション開発者には、非同期操作の結果にアクセスするためのデザインとして、いくつかの選択肢があります。正しい選択は、操作完了時に実行できる命令がアプリケーションにあるかどうかによって異なります。アプリケーションが非同期操作の結果を受け取るまで他の作業を実行できない場合は、結果が使用可能になるまで、そのアプリケーションをブロックする必要があります。非同期操作が完了するまでブロックするには、次のいずれかの方法を使用します。
アプリケーションのメイン スレッドから EndOperationName を呼び出し、操作完了までアプリケーションの実行をブロックします。この手法の例については、「非同期操作の終了によるアプリケーション実行のブロック」を参照してください。
AsyncWaitHandle を使用して、1 つ以上の操作が完了するまで、アプリケーションの実行をブロックします。この手法の例については、「AsyncWaitHandle の使用によるアプリケーション実行のブロック」を参照してください。
非同期操作が完了するまでアプリケーションをブロックする必要がない場合は、次のいずれかの方法を使用します。
操作完了ステータスをポーリングします。IsCompleted プロパティを定期的に確認し、操作が完了したときに EndOperationName を呼び出します。この手法の例については、「非同期操作のステータスのポーリング」を参照してください。
AsyncCallback デリゲートを使用して、操作が完了したときに呼び出すメソッドを指定します。この手法の例については、「AsyncCallback デリゲートの使用による非同期操作の終了」を参照してください。
参照
概念
同期メソッドの非同期呼び出し
AsyncCallback デリゲートおよび状態オブジェクトの使用