次の方法で共有


トランザクション管理 (Data Exchange)

サーバーとの会話を確立した後、クライアントはトランザクションを送信して、サーバーからデータとサービスを取得できます。

次のトピックでは、クライアントがサーバーとの対話に使用できるトランザクションの種類について説明します。

トランザクションの要求

クライアント アプリケーションは、XTYP_REQUEST トランザクションを使用して、サーバー アプリケーションにデータ項目を要求できます。 クライアントは DdeClientTransaction 関数を呼び出し、トランザクションの種類として XTYP_REQUEST を指定し、アプリケーションで必要なデータ項目を指定します。

動的データ交換管理ライブラリ (DDEML) は、クライアントによって要求されたトピック名、アイテム名、およびデータ形式を指定して、XTYP_REQUEST トランザクションをサーバーに渡します。 サーバーが要求されたトピック、項目、および形式をサポートしている場合、サーバーはアイテムの現在の値を識別するデータ ハンドルを返す必要があります。 DDEML は、DdeClientTransactionからの戻り値として、このハンドルクライアントに渡します。 要求 トピック、アイテム、または形式がサポートされていない場合、サーバーは NULL を返す必要があります。

DdeClientTransactionは、lpdwResult パラメーターを使用して、トランザクション状態フラグをクライアントに返します。 サーバーが XTYP_REQUEST トランザクションを処理しない場合、DdeClientTransaction は null 返し、lpdwResult はDDE_FNOTPROCESSEDまたはDDE_FBUSY フラグを指します。 DDE_FNOTPROCESSED フラグが返された場合、クライアントはサーバーがトランザクションを処理しなかった理由を判断できません。

サーバーが XTYP_REQUEST トランザクションをサポートしていない場合は、DdeInitialize 関数で CBF_FAIL_REQUESTS フィルター フラグを指定する必要があります。 このフラグにより、DDEML はトランザクションをサーバーに送信できなくなります。

ポケトランザクション

クライアントは、DdeClientTransaction使用してサーバーに要求されていないデータを送信し、XTYP_POKE トランザクションをサーバーのコールバック関数に送信できます。

クライアント アプリケーションは、まず、サーバーに送信するデータを含むバッファーを作成し、DdeClientTransactionするためのパラメーターとしてバッファーへのポインターを渡します。 または、クライアントは、DdeCreateDataHandle 関数を使用して、データを識別するデータ ハンドルを取得し、そのハンドルを渡して DdeClientTransaction できます。 どちらの場合も、クライアントは DdeClientTransaction 呼び出すときに、トピック名、項目名、およびデータ形式も指定します。

DDEML は、クライアントが要求したトピック名、項目名、およびデータ形式を指定して、XTYP_POKE トランザクションをサーバーに渡します。 データ項目と形式を受け入れるために、サーバーはDDE_FACKを返す必要があります。 データを拒否するには、サーバーはDDE_FNOTPROCESSEDを返す必要があります。 サーバーがビジー状態でデータを受け入れられない場合、サーバーはDDE_FBUSY返す必要があります。

DdeClientTransaction戻るときに、クライアントは lpdwResult パラメーターを使用してトランザクション状態フラグにアクセスできます。 フラグがDDE_FBUSYの場合、クライアントは後でトランザクションをもう一度送信する必要があります。

サーバーが XTYP_POKE トランザクションをサポートしていない場合は、DdeInitializeで CBF_FAIL_POKES フィルター フラグ指定する必要があります。 このフラグにより、DDEML はこのトランザクションをサーバーに送信できなくなります。

トランザクションのアドバイス

クライアント アプリケーションは、DDEML を使用して、サーバー アプリケーション内の項目への 1 つ以上のリンクを確立できます。 このようなリンクが確立されると、サーバーはリンクされたアイテムに関する定期的な更新をクライアントに送信します (通常、サーバー アプリケーションに関連付けられている項目の値が変更されるたびに)。 リンクを設定すると、クライアントが終了するまで 2 つのアプリケーション間にアドバイズ ループが確立されます。

アドバイズ ループには、"hot" と "warm" の 2 種類があります。ホット アドバイズ ループでは、サーバーは変更された値を識別するデータ ハンドルをすぐに送信します。 ウォーム アドバイズ ループでは、サーバーはアイテムの値が変更されたことをクライアントに通知しますが、クライアントが要求するまでデータ ハンドルを送信しません。

クライアントは、DdeClientTransactionの呼び出しで XTYP_ADVSTART トランザクションの種類を指定することで、サーバーでホット アドバイズ ループ要求できます。 ウォーム アドバイズ ループを要求するには、クライアントはXTYPF_NODATA フラグと XTYP_ADVSTART トランザクションの種類を組み合わせる必要があります。 いずれの場合も、DDEML は XTYP_ADVSTART トランザクションをサーバーの Dynamic Data Exchange (DDE) コールバック関数に渡します。 サーバーの DDE コールバック関数は、XTYP_ADVSTART トランザクションに付随するパラメーター (要求された形式、トピック名、およびアイテム名を含む) を調べ、TRUE を返して、アドバイズ ループまたは FALSE で拒否できるようにする必要があります。

アドバイズ ループが確立された後、要求された項目名に関連付けられている項目の値が変更されるたびに、サーバー アプリケーションは DdePostAdvise 関数を呼び出す必要があります。 この呼び出しにより、XTYP_ADVREQ トランザクションがサーバー独自の DDE コールバック関数に送信されます。 サーバーの DDE コールバック関数は、データ項目の新しい値を識別するデータ ハンドルを返す必要があります。 次に、DDEML は、XTYP_ADVDATA トランザクションをクライアントの DDE コールバック関数に送信することによって、指定された項目が変更されたことをクライアントに通知します。

クライアントがホット アドバイズ ループを要求した場合、DDEML は、XTYP_ADVDATA トランザクション中に変更された項目にデータ ハンドルをクライアントに渡します。 それ以外の場合、クライアントは XTYP_REQUEST トランザクションを送信してデータ ハンドルを取得できます。

サーバーは、クライアントが新しいデータを処理するよりも速く更新プログラムを送信できます。 更新の速度は、データに対して長い処理操作を実行する必要があるクライアントにとって問題になる可能性があります。 この場合、クライアントは、アドバイズ ループを要求するときに、XTYPF_ACKREQ フラグを指定する必要があります。 このフラグは、サーバーが次のデータ項目を送信する前に、クライアントがデータ項目を受信して処理したことをクライアントが確認するのを待機させます。 XTYPF_ACKREQ フラグを使用して確立されたアドバイズ ループは、高速サーバーの方が堅牢ですが、更新を見逃す場合があります。 XTYPF_ACKREQ フラグなしで確立されたアドバイズ ループは、クライアントがサーバーに対応している限り、更新を見逃さないことを保証します。

クライアントは、DdeClientTransactionの呼び出しで XTYP_ADVSTOP トランザクションの種類指定することで、アドバイズ ループを終了できます。

サーバーがアドバイズ ループをサポートしていない場合は、DdeInitialize 関数でCBF_FAIL_ADVISES フィルター フラグを指定する必要があります。 このフラグにより、DDEML は XTYP_ADVSTART トランザクションと XTYP_ADVSTOP トランザクションをサーバーに送信できなくなります。

トランザクションの実行

クライアントは、XTYP_EXECUTE トランザクションを使用して、サーバーにコマンドまたは一連のコマンドを実行させることができます。

サーバー コマンドを実行するために、クライアントは最初にサーバーが実行するコマンド文字列を含むバッファーを作成し、次に DdeClientTransactionを呼び出すときにバッファーへのポインターまたはバッファーを識別するデータ ハンドル渡します。 その他の必須パラメーターには、会話ハンドル、項目名文字列ハンドル、書式指定、および XTYP_EXECUTE トランザクションの種類が含まれます。 実行データを渡すデータ ハンドルを作成するアプリケーションでは、DdeCreateDataHandle 関数の hszItem パラメーターに null 指定し、uFmt パラメーターにゼロを指定する必要があります。

DDEML は、XTYP_EXECUTE トランザクションをサーバーの DDE コールバック関数に渡し、コマンド文字列を識別する形式名、会話ハンドル、トピック名、およびデータ ハンドルを指定します。 サーバーがコマンドをサポートしている場合は、DdeAccessData 関数を使用してコマンド文字列へのポインターを取得し、コマンドを実行してから、DDE_FACKを返す必要があります。 サーバーがコマンドをサポートしていない場合、またはトランザクションを完了できない場合は、DDE_FNOTPROCESSEDを返す必要があります。 トランザクションを完了するにはビジー状態が多すぎる場合、サーバーはDDE_FBUSYを返す必要があります。

一般に、サーバーのコールバック関数は、次の例外を除いて戻る前に、XTYP_EXECUTE トランザクションを処理する必要があります。

  1. XTYP_EXECUTE トランザクションで渡されたコマンドがサーバーに終了を要求した場合、コールバック関数が XTYP_EXECUTEの処理から戻るまで、サーバーは終了しないでください。
  2. DDEML 再帰の問題を引き起こす可能性があるダイアログ ボックスや DDE トランザクションの処理などの操作をサーバーが実行する必要がある場合、サーバーは、実行トランザクションをブロックし、操作を実行して実行トランザクションの処理を再開するCBR_BLOCKリターン コードを返す必要があります。

DdeClientTransaction戻るときに、クライアントは lpdwResult パラメーターを使用してトランザクション状態フラグにアクセスできます。 フラグがDDE_FBUSYの場合、クライアントは後でトランザクションをもう一度送信する必要があります。

サーバーが XTYP_EXECUTE トランザクションをサポートしていない場合は、DdeInitialize 関数でCBF_FAIL_EXECUTESフィルター フラグを指定する必要があります。 これにより、DDEML はトランザクションをサーバーに送信できなくなります。

同期トランザクションと非同期トランザクション

クライアントは、同期トランザクションまたは非同期トランザクションを送信できます。 同期トランザクションでは、クライアントは、サーバーがトランザクションを処理するのを待機する最大時間を示すタイムアウト値を指定します。 DdeClientTransaction は、サーバーがトランザクションを処理するか、トランザクションが失敗するか、タイムアウト値が期限切れになるまで戻りません。 クライアントは、DdeClientTransaction 呼び出すときにタイムアウト値を指定します。

同期トランザクション中、クライアントはトランザクションが処理されるのを待っている間にモーダル ループに入ります。 クライアントは引き続きユーザー入力を処理できますが、DdeClientTransaction戻るまで、別の同期トランザクションを送信することはできません。

クライアントは、DdeClientTransactionで TIMEOUT_ASYNC フラグ指定して非同期トランザクションを送信します。 この関数は、トランザクションが開始された後に戻り、トランザクション識別子をクライアントに渡します。 サーバーが非同期トランザクションの処理を完了すると、DDEML は XTYP_XACT_COMPLETE トランザクションをクライアントに送信します。 XTYP_XACT_COMPLETE トランザクション中に DDEML がクライアントに渡すパラメーターの 1 つがトランザクション識別子です。 このトランザクション識別子と ddeClientTransaction によって返される識別子比較することで、クライアントはサーバーが処理を完了した非同期トランザクションを識別します。

クライアントは、非同期トランザクションの処理に役立つ DdeSetUserHandle 関数を使用できます。 この関数を使用すると、クライアントはアプリケーション定義の値を会話ハンドルとトランザクション識別子に関連付けることができます。 クライアントは、XTYP_XACT_COMPLETE トランザクション中に DdeQueryConvInfo 関数を使用して、アプリケーション定義の値を取得できます。 この関数により、アプリケーションはアクティブなトランザクション識別子の一覧を保持する必要はありません。

クライアントが同期トランザクションを使用してデータの要求を正常に完了すると、DDEML は、クライアントが受信したデータの使用を完了したタイミングを確認する方法はありません。 クライアント アプリケーションは、受信したデータ ハンドルを DdeFreeDataHandle 関数に渡し、ハンドルが使用されなくなることを DDEML に通知する必要があります。 同期トランザクションによって返されるデータ ハンドルは、クライアントによって実質的に所有されます。

サーバーが非同期トランザクションをタイムリーに処理しない場合、クライアントは DdeAbandonTransaction 関数を呼び出すことによって、トランザクションを破棄できます。 DDEML は、トランザクションに関連付けられているすべてのリソースを解放し、サーバーがトランザクションの処理を完了したときにトランザクションの結果を破棄します。 同期トランザクション中のタイムアウトは、トランザクションを実質的に取り消します。

非同期トランザクションメソッドは、大量の DDE トランザクションを送信しながら、計算などの大量の処理を同時に実行する必要があるアプリケーションに対して提供されます。 非同期メソッドは、DDE トランザクションを中断せずに他のタスクを完了できるように、DDE トランザクションの処理を一時的に停止する必要があるアプリケーションでも役立ちます。 他のほとんどの状況では、アプリケーションで同期メソッドを使用する必要があります。

同期トランザクションは保守が簡単で、非同期トランザクションよりも高速です。 ただし、一度に実行できる同期トランザクションは 1 つだけですが、多くの非同期トランザクションを同時に実行できます。 同期トランザクションでは、サーバーが遅いと、クライアントが応答を待機している間もアイドル状態のままになることがあります。 また、同期トランザクションにより、クライアントはモーダル ループに入り、アプリケーション独自のメッセージ ループでメッセージ フィルター処理をバイパスできます。

クライアントがメッセージをフィルター処理するフック プロシージャをインストールしている場合 (つまり、SetWindowsHookEx 関数の呼び出しでWH_MSGFILTERフックの種類を指定した場合)、同期トランザクションによってシステムはフック プロシージャをバイパスしません。 クライアントが同期トランザクションの終了を待機している間に入力イベントが発生すると、フック プロシージャはMSGF_DDEMGRフック コードを受け取ります。 同期トランザクション モーダル ループを使用する主な危険性は、ダイアログ ボックスによって作成されたモーダル ループがその操作を妨げる可能性があるということです。 DDEML が DLL によって使用されている場合は、非同期トランザクションを常に使用する必要があります。

トランザクション制御

アプリケーションは、特定の会話ハンドルに関連付けられているトランザクション、または会話ハンドルに関係なくすべてのトランザクションのいずれかによって、DDE コールバック関数へのトランザクションを中断できます。 この機能は、長い処理を必要とするトランザクションをアプリケーションが受信する場合に便利です。 このような場合、アプリケーションはCBR_BLOCKリターン コードを返して、トランザクションの会話ハンドルに関連付けられている将来のトランザクションを中断して、アプリケーションが他の会話を自由に処理できるようにします。

処理が完了すると、アプリケーションは DdeEnableCallback 関数を呼び出して、中断された会話に関連付けられているトランザクションを再開します。 DdeEnableCallback 呼び出すと、アプリケーションが会話を中断する原因になったトランザクションが DDEML によって再送信されます。 そのため、アプリケーションは、トランザクションを再処理せずに結果を取得して返すように、トランザクションの結果を格納する必要があります。

アプリケーションは、DdeEnableCallbackへの呼び出しでハンドルとEC_DISABLE フラグを指定することで、特定の会話ハンドルに関連付けられているすべてのトランザクション中断できます。 NULL ハンドルを指定すると、アプリケーションはすべての会話のすべてのトランザクションを中断できます。

会話が中断されると、DDEML は会話のトランザクションをトランザクション キューに保存します。 アプリケーションが会話を再び有効にすると、DDEML は保存されたトランザクションをキューから削除し、各トランザクションを適切なコールバック関数に渡します。 トランザクション キューの容量は大きくなりますが、トランザクションが失われるのを防ぐために、アプリケーションはできるだけ早く中断された会話を再び有効にする必要があります。

アプリケーションは、DdeEnableCallbackで EC_ENABLEALL フラグ指定することで、通常のトランザクション処理を再開できます。 トランザクション処理の再開をより制御するには、アプリケーションで EC_ENABLEONE フラグを指定できます。 このフラグは、トランザクション キューから 1 つのトランザクションを削除し、適切なコールバック関数に渡します。そのトランザクションが処理された後、会話は再度無効になります。

ddeEnableCallbackの呼び出しでEC_ENABLEONE フラグと会話ハンドル指定されている場合、トランザクションの処理後にその会話のみがブロックされます。 NULL 会話ハンドルが指定されている場合、会話でトランザクションが処理された後、すべての会話がブロックされます。

トランザクション クラス

DDEML には、トランザクションの 4 つのクラスがあります。 各クラスは、XCLASS_ プレフィックスで始まる定数によって識別されます。 クラスは DDEML ヘッダー ファイルで定義されます。 クラス値はトランザクション型の値と組み合わされ、受信側アプリケーションの DDE コールバック関数に渡されます。

トランザクションのクラスは、コールバック関数がトランザクションを処理する場合に返される戻り値を決定します。 次の戻り値とトランザクションの種類は、4 つの各トランザクション クラスに関連付けられています。

クラス 戻り値 トランザクション
XCLASS_BOOL TRUE または FALSE XTYP_ADVSTART
XTYP_CONNECT
XCLASS_DATA データ ハンドル、CBR_BLOCKリターン コード、または NULL XTYP_ADVREQ
XTYP_REQUEST
XTYP_WILDCONNECT
XCLASS_FLAGS トランザクション フラグ: DDE_FACK、DDE_FBUSY、またはDDE_FNOTPROCESSED XTYP_ADVDATA
XTYP_EXECUTE
XTYP_POKE
XCLASS_NOTIFICATION 何一つ XTYP_ADVSTOP
XTYP_CONNECT_CONFIRM
XTYP_DISCONNECT
XTYP_ERROR
XTYP_REGISTER
XTYP_UNREGISTER
XTYP_XACT_COMPLETE

トランザクションの種類

各 DDE トランザクションの種類には、受信者と、DDEML が各型を生成するアクティビティが関連付けられています。

トランザクションの種類 受話器 原因
XTYP_ADVDATA クライアント サーバーは、データ ハンドルを返すことによって、XTYP_ADVREQ トランザクションに応答しました。
XTYP_ADVREQ サーバー DdePostAdvise 関数を呼び出したサーバー。アドバイズ ループ内のデータ項目の値が変更されたことを示します。
XTYP_ADVSTART サーバー クライアントは、DdeClientTransaction 関数の呼び出しで XTYP_ADVSTART トランザクションの種類を指定しました。
XTYP_ADVSTOP サーバー クライアントは、DdeClientTransactionの呼び出しで XTYP_ADVSTOP トランザクションの種類を指定しました。
XTYP_CONNECT サーバー クライアントは、DdeConnect 関数を呼び出し、サーバーでサポートされているサービス名とトピック名を指定しました。
XTYP_CONNECT_CONFIRM サーバー サーバーは、XTYP_CONNECT または XTYP_WILDCONNECT トランザクションに応答して TRUE 返しました。
XTYP_DISCONNECT クライアント/サーバー DdeDisconnect 関数と呼ばれる会話のパートナー。これにより、両方のパートナーがこのトランザクションを受け取ります。
XTYP_ERROR クライアント/サーバー 重大なエラーが発生しました。 DDEML には、続行するのに十分なリソースがない可能性があります。
XTYP_EXECUTE サーバー クライアントは、ddeClientTransactionの呼び出しで XTYP_EXECUTE トランザクションの種類指定しました。
XTYP_MONITOR DDE 監視アプリケーション DDE イベントがシステムで発生しました。 DDE 監視アプリケーションの詳細については、「監視アプリケーションの」を参照してください。
XTYP_POKE サーバー クライアントは、DdeClientTransactionの呼び出しで XTYP_POKE トランザクションの種類を指定しました。
XTYP_REGISTER クライアント/サーバー サーバー アプリケーションは、DdeNameService 関数を使用してサービス名を登録しました。
XTYP_REQUEST サーバー クライアントが DdeClientTransactionへの呼び出しで XTYP_REQUEST トランザクションの種類指定しました。
XTYP_UNREGISTER クライアント/サーバー DdeNameService使用してサービス名の登録を解除するサーバー アプリケーション。
XTYP_WILDCONNECT サーバー DdeConnect または DdeConnectList関数を呼び出し、サービス名、トピック名、またはその両方 NULL を指定します。
XTYP_XACT_COMPLETE クライアント クライアントが DdeClientTransactionの呼び出しでTIMEOUT_ASYNC フラグ指定したときに送信される非同期トランザクションが終了しました。