非同期プログラミングの概要
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 メソッド シグネチャの最後のパラメーターになります。
BeginOperationName は、呼び出し元スレッドに即座に制御を戻します。 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 に設定し、非同期コールバックが指定されている場合はそれを呼び出し、AsyncWaitHandle をシグナル状態にします。 |
アプリケーション開発者には、非同期操作の結果にアクセスするためのデザインとして、いくつかの選択肢があります。 適切な選択は、操作の完了前に実行できる命令がアプリケーションにあるかどうかによって異なります。 アプリケーションが非同期操作の結果を受け取るまで他の作業を実行できない場合は、結果が使用可能になるまで、そのアプリケーションをブロックする必要があります。 非同期操作が完了するまでブロックするには、次のいずれかの方法を使用します。
アプリケーションのメイン スレッドから EndOperationName を呼び出し、操作完了までアプリケーションの実行をブロックします。 この手法の例については、「非同期操作の終了によるアプリケーション実行のブロック」を参照してください。
AsyncWaitHandle を使用して、1 つ以上の操作が完了するまで、アプリケーションの実行をブロックします。 この手法の例については、「AsyncWaitHandle の使用によるアプリケーション実行のブロック」を参照してください。
非同期操作が完了するまでアプリケーションをブロックする必要がない場合は、次のいずれかの方法を使用します。
操作完了ステータスをポーリングします。IsCompleted プロパティを定期的に確認し、操作が完了したときに EndOperationName を呼び出します。 この手法の例については、「非同期操作のステータスのポーリング」を参照してください。
AsyncCallback デリゲートを使用して、操作が完了したときに呼び出されるメソッドを指定します。 この手法の例については、「AsyncCallback デリゲートの使用による非同期操作の終了」を参照してください。
参照
概念
AsyncCallback デリゲートおよび状態オブジェクトの使用