イベントベースの非同期パターンの実装時期を決定する

イベント ベースの非同期パターンは、クラスの非同期動作を公開します。 このパターンの導入に伴い、.NET では、非同期動作を公開する 2 つのパターンとして、System.IAsyncResult インターフェイスに基づく非同期パターンとイベント ベースのパターンが定義されています。 この記事では、両方のパターンをどのような状況で実装するべきか説明します。

IAsyncResult インターフェイスによる非同期プログラミングについて詳しくは、「非同期プログラミング モデル (APM)」をご覧ください。

一般原則

一般的に、可能であれば、イベント ベースの非同期パターンを利用して非同期機能を公開してください。 ただし、イベント ベースのパターンでは満たせない要件もあります。 そのようなとき、場合によっては、イベント ベースのパターンに加え、IAsyncResult パターンも実装する必要があります。

注意

イベント ベースのパターンを実装せずに IAsyncResult パターンのみを実装することはまれです。

ガイドライン

次の一覧は、イベント ベースの非同期パターンを実装するときのガイドラインをまとめたものです。

  • 既定の API としてイベント ベースのパターンを使用し、クラスの非同期動作を公開します。

  • クラスが主に、Windows フォームなど、クライアント アプリケーションで使用されるとき、IAsyncResult パターンを公開しないでください。

  • 要件を満たすために必要なときにのみ、IAsyncResult パターンを公開します。 たとえば、既存の API との互換性を得るために IAsyncResult パターンを公開する必要がある場合です。

  • IAsyncResult パターンを公開するときは、イベント ベースのパターンも公開してください。

  • IAsyncResult パターンを公開する必要がある場合、詳細設定のオプションとしてそれを行います。 たとえば、プロキシ オブジェクトを生成する場合、既定でイベント ベースのパターンを生成し、IAsyncResult パターンを生成するオプションを指定します。

  • IAsyncResult パターンの実装を基盤にしてイベント ベースのパターンを実装します。

  • 同じクラスでイベント ベースのパターンと IAsyncResult パターンの両方を公開することは避けます。 イベント ベースのパターンを "上位" クラスで公開し、IAsyncResult パターンを "下位" クラスで公開します。 たとえば、WebClient コンポーネントのイベント ベースのパターンと HttpRequest クラスの IAsyncResult パターンを比較します。

    • 互換性のために必要なとき、イベント ベースのパターンと IAsyncResult パターンを同じクラスで公開します。 たとえば、IAsyncResult パターンを使用する API を既に公開している場合、後方互換性のために IAsyncResult パターンを維持する必要があります。

    • 最終的なオブジェクト モデルが複雑すぎて実装を分ける意味がなくなってしまう場合、イベント ベースのパターンと IAsyncResult パターンを同じクラスで公開します。 イベント ベースのパターンを公開することを避けるより、1 つのクラスで両方のパターンを公開するほうが得策です。

    • イベント ベースのパターンと IAsyncResult パターンを 1 つのクラスで公開する必要がある場合、Advanced に設定された EditorBrowsableAttribute を使用し、IAsyncResult パターンの実装を高度な機能として設定します。 これで Visual Studio IntelliSense のようなデザイン環境に、IAsyncResult のプロパティやメソッドを表示しないように指示されます。 これらのプロパティとメソッドには完全な有用性がまだ与えられていませんが、IntelliSense で開発している開発者は API を詳しく理解できます。

イベント ベースのパターンに加え、IAsyncResult パターンを公開する基準

前述のシナリオではイベント ベースの非同期パターンにさまざまな長所がありましたが、短所もあります。パフォーマンスが最も重要な要件であれば、その短所も考慮してください。

イベント ベースのパターンで IAsyncResult パターンも対処されないシナリオが 3 つあります。

  • 1 つの IAsyncResult に対する待機をブロックする

  • たくさんの IAsyncResult オブジェクトに対する待機をブロックする

  • IAsyncResult の完了に対するポーリング

以上のシナリオには、イベント ベースのパターンで対処できますが、IAsyncResult パターンを使用する場合より面倒になります。

開発者は多くの場合、一般的にパフォーマンス要件が非常に高いサービスに IAsyncResult パターンを使用します。 たとえば、完了のポーリング シナリオに該当するのが高性能サーバーを利用するときです。

また、イベント ベースのパターンは IAsyncResult パターンと比べて効率性が劣ります。作成されるオブジェクトが多く (特に EventArgs)、スレッド間で同期がとられるためです。

次の一覧は、IAsyncResult パターンを使用する場合の推奨事項をいくつか取り上げたものです。

  • WaitHandle または IAsyncResult オブジェクトのサポートが厳密に必要な場合にのみ IAsyncResult パターンを公開します。

  • 既存の API で IAsyncResult パターンを使用している場合にのみ IAsyncResult パターンを公開します。

  • 既存の API が IAsyncResult パターンに基づく場合、次のリリースでイベント ベースのパターンも公開することを検討します。

  • 検証済みの高いパフォーマンス要件がイベント ベースのパターンでは満たせないが、IAsyncResult パターンでは満たせる場合にのみ、IAsyncResult パターンを公開します。

参照