TThreadクラスでCOMを利用する方法 |
|
conundrum
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:893 回覆:1272 積分:643 註冊:2004-01-06 發送簡訊給我 |
http://www.borland.co.jp/delphi/papers/com/com05.html 5-1.TThreadクラスでCOMを利用する方法 ■TThreadクラスとは Delphiでセカンダリスレッドを明示的に作成するには、TThreadクラスを利用します。 TThreadクラスは、インスタンスが作成されるとスレッドが作成され、そのスレッドによりExecuteメソッドが実行されます。 別スレッドで実行したいプログラムは、TThread.Executeメソッドに実装します。 ■TThreadクラスでCOMを利用する方法 TThreadクラスでCOMを利用する方法は、いままで解説したとおりです。 Executeメソッドはスレッドで実行されているため、ExecuteメソッドでCOMを利用する場合は、スレッドをアパートに入れなければなりません。また、アパート境界を越えてインターフェース ポインタを受け渡す場合は、インターフェース ポインタのマーシャリングやアンマーシャリングが必要になります。 リスト:スレッドオブジェクトのExecuteメソッドでCOMを利用する例 type TUseOnlyThread = class(TThread) private protected procedure Execute; override; end; implementation procedure TUseOnlyThread.Execute; var SampleInterface: ISampleServer; begin // このスレッドをSTAに入れる CoInitializeEx(nil, COINIT_APARTMENTTHREADED); try // COMを利用 SampleInterface := CoSampleServer.Create; SampleInterface.Method1; SampleInterface := nil; finally // スレッドを終了する前に、COMの終了処理を行う CoUninitialize; end; end; ■デモプログラム TThreadクラスを使って、セカンダリスレッドからCOMを利用するデモプログラムを用意しました。 COMのスレッドに関する規則を学習するために、故意に規則違反をしてエラーを発生させるプログラムと、規則を守っているプログラムが実装されています。 デモプログラムのソースコードを参照することで、次の事が学習できます。 スレッドをアパートに入れる方法 インターフェース ポインタをマーシャリングおよびアンマーシャリングする方法 どのようなときCOMのスレッドに関する規則違反になるのか デモプログラムの動作方法などは、デモプログラムに添付されているreadme.txtをご覧ください。 ■TThreadクラスでCOMを利用するときの注意点 TThreadクラスでCOMを利用するときの注意点は、次の通りです。 作成したスレッドで実行されているのは、Executeメソッドだけ Executeメソッドとその他のメソッドが実行されるスレッドは異なります。 一番注意しなければならないのが、OnTerminateイベントハンドラです。 OnTerminateイベントハンドラが実行されるスレッドは、TThreadクラスで作成したスレッドではなく、プライマリ スレッドになります。そのため、OnTerminateイベントハンドラでCoUninitialize関数を呼び出すと、プライマリ スレッドに対して呼び出すことになります。 スレッドでCOMを利用した場合、COMの終了処理はOnTerminateイベントハンドラではなく、Executeメソッドで行ってください。 SynchronizeメソッドからSTA内のメソッドを呼び出せない COMでは、STAに属するCOMオブジェクトのメソッド呼び出しは一本化されますが、デッドロックを防ぐため、再入できるようになっています。しかし、別スレッドからSendMessage関数で送られたメッセージを受け取ったルーチン内で、STAに属するCOMオブジェクトのメソッドを呼び出すと、デッドロックが起こる可能性があります。このため、このようなメソッド呼び出しはエラーになります。 TThread.Synchronizeメソッドは、パラメータで指定されたメソッドをプライマリ スレッドで実行するために、SendMessage関数を使って、パラメータで指定されたメソッドを実行します。そのため、そのメソッド内でSTAに属するCOMオブジェクトのメソッドを呼び出すと、エラーが発生しますので注意してください。 ※デモプログラムの[SynchronizeメソッドからSTA内のメソッドを呼び出す]ボタンがそのような動作をするスレッドです。 5-2.リモートデータモジュールでCOMを利用する方法 ■リモートデータモジュールとは リモートデータモジュールとは、1つのCOMオブジェクトを表すデータモジュールです。 リモートデータモジュールは、Delphi 5 Enterprise版で多層C/Sシステムを迅速に開発するためのフレームワークであるMIDAS(Multi-tier Distributed Application Services Suite)などのアプリケーションサーバー上で実行するビジネスロジックを実装するために利用されます。 ■リモートデータモジュールの2つの立場 リモートデータモジュールは、「COMオブジェクトを提供する立場」と「COMオブジェクトを利用する立場」の2つの立場があります。 まず、リモートデータモジュール自身が1つのCOMオブジェクトを表しているため、COMオブジェクトを提供する立場になります。 また、リモートデータモジュールからもADO(ActiveX Data Objects)などのCOMオブジェクトを利用できるため、COMオブジェクトを利用する立場にもなります。 それでは、各立場ごとに解説しましょう。 ■COMオブジェクトを提供する立場 リモートデータモジュールもCOMオブジェクトですので、普通のCOMオブジェクトのプログラミングと同様にタイプライブラリエディタでインターフェースやメソッドを編集したり、スレッディングモデルを指定したりできます。 しかし、スレッディングモデルに関して注意する点があります。 (A)同じプロセスにtmFreeとtmSingleのスレッディング モデルは同居できない (B)tmApartmentは実質的に使えない (A)は、Delphi 5ではtmFreeのCOMオブジェクトが存在するとプライマリ スレッドがMTAに入るため、プライマリ スレッドから作成されるtmSingleのCOMオブジェクトもMTAに入ってしまうので同居できません。この場合は、プロジェクトを分けてプロセスを分割します。 (B)は、Delphi 5ではTComponentFactoryクラス(リモートデータモジュールのCOMオブジェクトを作成するクラスファクトリ)がCOMオブジェクトを作成する毎にスレッドとSTAを作成します。Delphi 4以前では、tmApartmentを指定してもtmSingleと同様、COMオブジェクトがプライマリ スレッドのアパートに入るためtmFreeと同居できませんでした。これを改善するためにDelphi 5では、このように変更されました。 しかし、これによりアプリケーション サーバー上で利用する場合、あらたな問題が発生します。 スレッドは、待ち状態でもオーバーヘッドが発生します。COMオブジェクト毎にスレッドを作成すると、多くのクライアントがCOMオブジェクトを作成した場合、大量のスレッドが作成されるため、相当なオーバーヘッドが発生します。このため、アプリケーションサーバー上では、tmApartmentは実質的に使えません。 mtFreeであれば、スレッドはCOMが準備しているスレッドプールから提供されます。スレッドプールにあるスレッドの数は、負荷にあわせて自動的に増減されるので、たくさんのCOMオブジェクトを作成しても待ち状態の無駄なスレッドが大量に作られることはありません。 この点を考慮したリモートデータモジュールのスレッディングモデルの選択方法は、次のとおりです。 アクセス頻度が低い場合 スレッディングモデルにtmSingleを選択します。 ただし、tmSingleはmtFreeと同居できないため、tmSingleのリモートデータモジュールだけを集めて1つのプロジェクトにしてください。 また、tmSingleのCOMオブジェクトしかないプロジェクトでは、すべてのCOMオブジェクトがプライマリ スレッドで動作するためBDEセッションを分割する必要が無くなります。そのため1つのTDatabaseコンポーネントによるデータベース接続を共有することもできます。 アクセス頻度が高い場合 スレッディングモデルにtmFreeを選択します。 ただし、tmFreeを選択すると、COMオブジェクトはMTAに入るため、マルチスレッドを意識したプログラミングが必要になります。 データベース接続にBDEを利用する場合、注意が必要です。BDEを使ってデータベースに接続するためには、データベースの情報やカーソルなどコンテキストが格納されたBDEセッションが必要になります。このBDEセッションはスレッドセーフではありません。そのため、スレッド毎にBDEセッションを個別に割り当てなければなりません。 多くの場合、複数のスレッドから1つのCOMオブジェクトにアクセスすることは無いため、リモートデータモジュール毎にBDEセッションを表すTSessionコンポーネントを割り当てるだけで充分です。なお、TSessionコンポーネントの割り当ては、リモートデータモジュール上にTSessionコンポーネントを配置して、TSession.AutoSessionNameプロパティにTrueを設定するだけです。 tmFreeにすると、プログラミングによっては、COMオブジェクトごとにデータベースに接続するため、たくさんのCOMオブジェクトを作成すると、データベースへの接続数が増え、データベース サーバーに負担が掛かります。これを解消するには、少ない資源で多くのクライアントを処理することができるMTS(Microsoft Transaction Server)などTPモニターを利用しなくてはなりません。 ■COMオブジェクトを利用する立場 リモートデータモジュールからCOMを利用するときは、リモートデータモジュールのCOMオブジェクトが入っているアパートを考慮して、COMのスレッドに関する規則を守るだけです。 ただし、ADOを利用する場合には、少し注意が必要です。B ADOが提供するCOMオブジェクト(ADOオブジェクト)のスレッディングモデルは、ADOインストール時に「Apartment」に設定されます。これは、Microsoft Accessデータベース エンジンがApartmentしか対応していないためです。このままでは、ADOオブジェクトがSTAに入るため、mtFreeのリモートデータモジュールからADOを利用すると、アパート境界を越えるためのプロキシを経由するためオーバーヘッドが掛かりますし、STAによってADOオブジェクトの呼び出しが一本化されるため時間の掛かるSQLを発行すると他の呼び出しが待たされることになります。 なお、SQL ServerなどのOLE DBプロバイダは、Bothスレッディング モデルに対応しています。これらのOLE DBプロバイダを利用することが決まっている場合は、次の方法により、ADOオブジェクトのスレッディング モデルをBothに変更することができます。 「C:\Program Files\Common Files\System\ado\adofre15.reg」を実行します。 これでADOオブジェクトをMTAに入れることができるため、mtFreeのリモートデータモジュールからオーバーヘッドなしにADOオブジェクトを利用することができます。 (重要)この方法は、利用するOLE DBプロバイダが対応しているスレッディング モデルを確認してから行ってください。 ADOのスレッディング モデルにつきましては、次のWebページをご覧ください。 Web Workshop - IIS 4.0におけるデータ アクセス コンポーネントのパフォーマンスの改善 ■デモプログラム リモートデータモジュールからBDEおよびADOを利用するデモプログラムを用意しました。 デモプログラムのソースコードを参照することで、次の事が学習できます。 スレッディングモデルがmtFreeのリモートデータモジュールからBDEとADOを利用する方法 デモプログラムの動作方法などは、デモプログラムに添付されているreadme.txtをご覧ください。 5-3.ISAPIアプリケーションでCOMを利用する方法 ■ISAPIアプリケーションとは ISAPIアプリケーションとは、マイクロソフト社のWebサーバー(IISやPWS)上で高速に動作するWebサーバーアプリケーションの名称です。 従来のCGIはプログラムがEXE形式になっており、Webブラウザからの要求ごとにプロセスの起動と終了を繰り返していたため、多くのオーバーヘッドが掛かりました。 しかし、ISAPIアプリケーションはDLL形式になっているため、Webブラウザからの要求ごとにプロセスの起動と終了を行う必要が無いため高速に動作することができます。 なお、Delphi 5 Enterprise版およびProfessional版では、Webサーバーアプリケーションを迅速に開発するためのフレームワークとして「WebBroker」を提供しています。一般的に、DelphiでISAPIアプリケーションを開発するときは、WebBrokerを利用します。 ■ISAPIアプリケーションでCOMを利用 Webブラウザから同時に複数の要求が発生した場合は、複数のスレッドによりISAPIアプリケーションが実行されます。 このときISAPIアプリケーションを実行するスレッドは、ISAPIアプリケーションが用意するのではなく、Webサーバーが用意したスレッドが使用されます。 IIS4.0およびPWS4.0では、ISAPIアプリケーションを実行するスレッドは、WebサーバーによってMTAに入れられています。 そのためISAPIアプリケーションで、CoInitializeEx関数を呼び出してアパートに入れる必要はありません。また、ISAPIアプリケーションを実行するスレッドがランダムに割り当てられても、すべてのスレッドが同じMTAに入っているため、インターフェース ポイӥ |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |