マルチスレッドコンピュータプログラミングにおいて、非同期メソッド呼び出し(AMI)、別名非同期メソッドコールまたは非同期パターンは、呼び出し元のスレッドが呼び出されたコードの完了を待つ間ブロックされない設計パターンです。代わりに、応答が到着したときに呼び出し元のスレッドに通知されます。応答をポーリングすることは望ましくない方法です。
AMI は、オブジェクトの潜在的に長時間実行されるメソッドを非同期で呼び出すための設計パターンです。[ 1 ] これは、1996 年に Allan Vermeulen によって記述された IOU ("I owe you") パターンと同等です。[ 2 ] [ 3 ]
ほとんどのプログラミング言語では、呼び出されたメソッドは同期的に実行されます。つまり、メソッドが呼び出された実行スレッド内で実行されます。メソッドの完了に時間がかかる場合(たとえば、インターネット経由でデータをロードする場合)、メソッドが終了するまで呼び出し元のスレッドはブロックされます。このような状態を避けたい場合は、「ワーカー スレッド」を開始して、そこからメソッドを呼び出すことができます。ほとんどのプログラミング環境では、特に多数のスレッドを作成することで発生するオーバーヘッドを回避するように注意すると、これには多くのコード行が必要になります。AMI は、実行に時間がかかる可能性のある(「同期」)オブジェクト メソッドに、即座に結果を返す「非同期」バリアントを追加することでこの問題を解決します。また、完了通知を簡単に受け取ったり、後で完了を待ったりできる追加メソッドも提供します。
AMI の一般的な用途の 1 つは、アクティブ オブジェクトデザイン パターンです。代替案としては、同期メソッド呼び出しとフューチャー オブジェクトがあります。[ 4 ] AMI を利用する可能性のあるアプリケーションの例としては、すべての画像が読み込まれる前に Web ページを表示する必要がある Web ブラウザーがあります。
メソッドはプロシージャの特殊なケースであるため、非同期メソッド呼び出しは非同期プロシージャ呼び出しの特殊なケースです。
Java のFutureTask クラス[ 5 ]はイベントを使用して同じ問題を解決します。このパターンは AMI のバリアントであり、実装にはより多くのオーバーヘッドがありますが、ソフトウェア コンポーネントを表すオブジェクトには役立ちます。
以下の例は、.NET Frameworkで使用される標準的な AMI スタイルを大まかにベースにしています。[ 9 ] メソッド が与えられた場合Accomplish、2 つの新しいメソッドBeginAccomplishとを追加しますEndAccomplish。
class Example { Result Accomplish ( args … ) IAsyncResult BeginAccomplish ( args … ) Result EndAccomplish ( IAsyncResult a ) … }を呼び出すと、クライアントはすぐに型(インターフェースを実装する)BeginAccomplishのオブジェクトを受け取り、呼び出し元のスレッドを無関係な作業で続行できます。最も単純なケースでは、最終的にそのような作業はなくなり、クライアントは(以前に受け取ったオブジェクトを渡して) を呼び出します。これは、メソッドが完了して結果が利用可能になるまでブロックします。[ 10 ]オブジェクトは通常、クライアントが長時間実行されるメソッドが既に完了したかどうかを問い合わせることができるメソッドを少なくとも1つ提供します。AsyncResultIAsyncResultEndAccomplishAsyncResult
interface IAsyncResult { bool HasCompleted () … }BeginAccomplish長時間実行されるメソッドが完了したときに呼び出されるコールバック メソッドを に渡すこともできます。通常EndAccomplish、長時間実行されるメソッドの戻り値を取得するために を呼び出します。コールバック メカニズムの問題点は、コールバック関数が(元の呼び出しスレッドではなく)ワーカー スレッドで実行されるため、競合状態が発生する可能性があることです。[ 11 ] [ 12 ]
AccomplishAsync.NET Framework のドキュメントでは、イベントベースの非同期パターンという用語は、 の代わりにという名前のメソッドを使用する代替 API スタイル (.NET 2.0 以降で利用可能) を指しますBeginAccomplish。[ 13 ] [ 14 ] 表面的な違いは、このスタイルでは、長時間実行されるメソッドの戻り値がコールバック メソッドに直接渡されることです。さらに重要なのは、この API は、が呼び出されたAccomplishCompletedのと同じスレッドでコールバック メソッド ( 型のイベント オブジェクト内に存在する) を実行するための特別なメカニズムを使用することですBeginAccomplish。これにより、競合状態の危険性が排除され、API が使いやすくなり、ソフトウェア コンポーネントに適しています。一方で、このパターンの実装には、追加のオブジェクト作成と同期のオーバーヘッドが伴います。[ 15 ]
{{cite journal}}:ジャーナルを引用するには|journal=(ヘルプ)