Gestione delle transazioni (Scambio di dati)
Dopo aver stabilito una conversazione con un server, un client può inviare transazioni per ottenere dati e servizi dal server.
Negli argomenti seguenti vengono descritti i tipi di transazioni che i client possono usare per interagire con un server.
- Richiedi transazione
- Transazione poke
- Consigliare la transazione
- Esegui transazione
- Transazioni sincrone e asincrone
- Controllo delle transazioni
- Classi di transazioni
- Natura transazione
Richiedi transazione
Un'applicazione client può usare la transazione XTYP_REQUEST per richiedere un elemento di dati da un'applicazione server. Il client chiama la funzione DdeClientTransaction , specificando XTYP_REQUEST come tipo di transazione e specificando l'elemento di dati necessario per l'applicazione.
Dynamic Data Exchange Management Library (DDEML) passa la transazione XTYP_REQUEST al server, specificando il nome dell'argomento, il nome dell'elemento e il formato dei dati richiesti dal client. Se il server supporta l'argomento, l'elemento e il formato richiesti, il server deve restituire un handle di dati che identifica il valore corrente dell'elemento. DDEML passa questo handle al client come valore restituito da DdeClientTransaction. Il server deve restituire NULL se non supporta l'argomento, l'elemento o il formato richiesto.
DdeClientTransaction usa il parametro lpdwResult per restituire un flag di stato della transazione al client. Se il server non elabora la transazione XTYP_REQUEST, DdeClientTransaction restituisce NULL e lpdwResult punta al flag DDE_FNOTPROCESedizione Standard D o DDE_FBUSY. Se viene restituito il flag DDE_FNOTPROCESedizione Standard D, il client non può determinare il motivo per cui il server non ha elaborato la transazione.
Se un server non supporta la transazione XTYP_REQUEST, deve specificare il flag di filtro CBF_FAIL_REQUESTS nella funzione DdeInitialize. Questo flag impedisce al DDEML di inviare la transazione al server.
Transazione poke
Un client può inviare dati non richiesti a un server usando DdeClientTransaction per inviare una transazione XTYP_POKE alla funzione di callback di un server.
L'applicazione client crea innanzitutto un buffer che contiene i dati da inviare al server e quindi passa un puntatore al buffer come parametro a DdeClientTransaction. In alternativa, il client può usare la funzione DdeCreateDataHandle per ottenere un handle di dati che identifica i dati e quindi passare l'handle a DdeClientTransaction. In entrambi i casi, il client specifica anche il nome dell'argomento, il nome dell'elemento e il formato dati quando chiama DdeClientTransaction.
DDEML passa la transazione XTYP_POKE al server, specificando il nome dell'argomento, il nome dell'elemento e il formato di dati richiesti dal client. Per accettare l'elemento di dati e il formato, il server deve restituire DDE_FACK. Per rifiutare i dati, il server deve restituire DDE_FNOTPROCESedizione Standard D. Se il server è troppo occupato per accettare i dati, il server deve restituire DDE_FBUSY.
Quando DdeClientTransaction viene restituito, il client può usare il parametro lpdwResult per accedere al flag di stato della transazione. Se il flag è DDE_FBUSY, il client deve inviare nuovamente la transazione in un secondo momento.
Se un server non supporta la transazione XTYP_POKE, deve specificare il flag di filtro CBF_FAIL_POKES in DdeInitialize. Questo flag impedisce al DDEML di inviare la transazione al server.
Consigliare la transazione
Un'applicazione client può usare DDEML per stabilire uno o più collegamenti a elementi in un'applicazione server. Quando è stato stabilito un collegamento di questo tipo, il server invia aggiornamenti periodici sull'elemento collegato al client (in genere, ogni volta che cambia il valore dell'elemento associato all'applicazione server). Il collegamento stabilisce un ciclo di consigli tra le due applicazioni che rimangono sul posto fino al termine del client.
Esistono due tipi di cicli di consiglio: "caldo" e "caldo". In un ciclo di avviso frequente, il server invia immediatamente un handle dati che identifica il valore modificato. In un ciclo warm advise, il server notifica al client che il valore dell'elemento è stato modificato ma non invia l'handle di dati fino a quando il client non lo richiede.
Un client può richiedere un ciclo di consulenza frequente con un server specificando il tipo di transazione XTYP_ADVSTART in una chiamata a DdeClientTransaction. Per richiedere un ciclo warm advise, il client deve combinare il flag XTYPF_NODATA con il tipo di transazione XTYP_ADVSTART . In entrambi i casi, DDEML passa la transazione XTYP_ADVSTART alla funzione di callback DDE (Dynamic Data Exchange) del server. La funzione di callback DDE del server deve esaminare i parametri che accompagnano la transazione XTYP_ADVSTART (incluso il formato richiesto, il nome dell'argomento e il nome dell'elemento) e quindi restituire TRUE per consentire il ciclo di consigli o FAL edizione Standard negarlo.
Dopo aver stabilito un ciclo di consigli, l'applicazione server deve chiamare la funzione DdePostAdvise ogni volta che il valore dell'elemento associato al nome dell'elemento richiesto cambia. Questa chiamata comporta l'invio di una transazione XTYP_ADVREQ alla funzione di callback DDE del server. La funzione di callback DDE del server deve restituire un handle di dati che identifica il nuovo valore dell'elemento di dati. DDEML invia quindi una notifica al client che l'elemento specificato è stato modificato inviando la transazione XTYP_ADVDATA alla funzione di callback DDE del client.
Se il client ha richiesto un ciclo di consulenza frequente, DDEML passa l'handle dati all'elemento modificato al client durante la transazione XTYP_ADVDATA. In caso contrario, il client può inviare una transazione XTYP_REQUEST per ottenere l'handle dati.
È possibile che un server invii aggiornamenti più velocemente di quanto un client possa elaborare i nuovi dati. La velocità degli aggiornamenti può essere un problema per un client che deve eseguire operazioni di elaborazione lunghe sui dati. In questo caso, il client deve specificare il flag XTYPF_ACKREQ quando richiede un ciclo di consigli. Questo flag fa sì che il server attenda che il client riconosca che ha ricevuto ed elaborato un elemento di dati prima che il server invii l'elemento dati successivo. Consiglia cicli che vengono stabiliti con il flag XTYPF_ACKREQ sono più affidabili con server veloci, ma possono occasionalmente perdere gli aggiornamenti. I cicli di avviso stabiliti senza il flag di XTYPF_ACKREQ sono garantiti per non perdere gli aggiornamenti, purché il client continui con il server.
Un client può terminare un ciclo di consigli specificando il tipo di transazione XTYP_ADVSTOP in una chiamata a DdeClientTransaction.
Se un server non supporta i cicli di avviso, deve specificare il flag di filtro CBF_FAIL_ADVIedizione Standard S nella funzione DdeInitialize. Questo flag impedisce al DDEML di inviare le transazioni XTYP_ADVSTART e XTYP_ADVSTOP al server.
Esegui transazione
Un client può usare la transazione di XTYP_EXECUTE per fare in modo che un server eseeseguono un comando o una serie di comandi.
Per eseguire un comando server, il client crea innanzitutto un buffer contenente una stringa di comando per il server da eseguire e quindi passa un puntatore al buffer o un handle di dati che identifica il buffer quando chiama DdeClientTransaction. Altri parametri obbligatori includono l'handle di conversazione, l'handle stringa del nome dell'elemento, la specifica del formato e il tipo di transazione XTYP_EXECUTE . Un'applicazione che crea un handle di dati per il passaggio dei dati di esecuzione deve specificare NULL per il parametro hszItem della funzione DdeCreateDataHandle e zero per il parametro uFmt.
DDEML passa la transazione XTYP_EXECUTE alla funzione di callback DDE del server e specifica il nome del formato, l'handle di conversazione, il nome dell'argomento e l'handle di dati che identificano la stringa di comando. Se il server supporta il comando, deve usare la funzione DdeAccessData per ottenere un puntatore alla stringa di comando, eseguire il comando e quindi restituire DDE_FACK. Se il server non supporta il comando o non riesce a completare la transazione, deve restituire DDE_FNOTPROCESedizione Standard D. Il server deve restituire DDE_FBUSY se è troppo occupato per completare la transazione.
In generale, la funzione di callback di un server deve elaborare la transazione XTYP_EXECUTE prima di restituire con le eccezioni seguenti:
- Quando il comando passato con la transazione XTYP_EXECUTE richiede il termine del server, il server non deve terminare fino a quando la funzione di callback non viene restituita dall'elaborazione XTYP_EXECUTE.
- Se il server deve eseguire un'operazione, ad esempio l'elaborazione di una finestra di dialogo o una transazione DDE che potrebbe causare problemi di ricorsione DDEML, il server deve restituire il codice restituito CBR_BLOCK per bloccare la transazione di esecuzione, eseguire l'operazione e quindi riprendere l'elaborazione della transazione di esecuzione.
Quando DdeClientTransaction restituisce il risultato, il client può usare il parametro lpdwResult per accedere al flag di stato della transazione. Se il flag è DDE_FBUSY, il client deve inviare nuovamente la transazione in un secondo momento.
Se un server non supporta la transazione XTYP_EXECUTE, deve specificare il flag di filtro CBF_FAIL_EXECUTES nella funzione DdeInitialize. In questo modo si impedisce al DDEML di inviare la transazione al server.
Transazioni sincrone e asincrone
Un client può inviare transazioni sincrone o asincrone. In una transazione sincrona, il client specifica un valore di timeout che indica la quantità massima di tempo di attesa per l'elaborazione della transazione da parte del server. DdeClientTransaction non restituisce finché il server non elabora la transazione, la transazione non riesce o il valore di timeout scade. Il client specifica il valore di timeout quando chiama DdeClientTransaction.
Durante una transazione sincrona, il client immette un ciclo modale durante l'attesa dell'elaborazione della transazione. Il client può comunque elaborare l'input dell'utente, ma non può inviare un'altra transazione sincrona fino a quando DdeClientTransaction non restituisce.
Un client invia una transazione asincrona specificando il flag TIMEOUT_ASYNC in DdeClientTransaction. La funzione restituisce dopo l'avvio della transazione, passando un identificatore di transazione al client. Quando il server termina l'elaborazione della transazione asincrona, DDEML invia una transazione XTYP_XACT_COMPLETE al client. Uno dei parametri passati dal DDEML al client durante la transazione XTYP_XACT_COMPLETE è l'identificatore della transazione. Confrontando questo identificatore di transazione con l'identificatore restituito da DdeClientTransaction, il client identifica la transazione asincrona che il server ha terminato l'elaborazione.
Un client può usare la funzione DdeSetUserHandle come supporto per l'elaborazione di una transazione asincrona. Questa funzione consente a un client di associare un valore definito dall'applicazione a un handle di conversazione e a un identificatore di transazione. Il client può usare la funzione DdeQueryConvInfo durante la transazione XTYP_XACT_COMPLETE per ottenere il valore definito dall'applicazione. A causa di questa funzione, un'applicazione non deve mantenere un elenco di identificatori di transazione attivi.
Quando un client completa correttamente una richiesta di dati usando una transazione sincrona, DDEML non è in grado di indicare quando il client ha terminato di usare i dati ricevuti. L'applicazione client deve passare l'handle di dati ricevuto alla funzione DdeFreeDataHandle , notificando al DDEML che l'handle non verrà più usato. Gli handle di dati restituiti dalle transazioni sincrone sono di proprietà del client.
Se un server non elabora una transazione asincrona in modo tempestivo, il client può abbandonare la transazione chiamando la funzione DdeAbandonTransaction. DDEML rilascia tutte le risorse associate alla transazione e rimuove i risultati della transazione al termine dell'elaborazione da parte del server. Un timeout durante una transazione sincrona annulla effettivamente la transazione.
Il metodo di transazione asincrono viene fornito per le applicazioni che devono inviare un volume elevato di transazioni DDE eseguendo contemporaneamente una notevole quantità di elaborazione, ad esempio l'esecuzione di calcoli. Il metodo asincrono è utile anche nelle applicazioni che devono interrompere temporaneamente l'elaborazione delle transazioni DDE in modo da poter completare altre attività senza interruzioni. Nella maggior parte delle altre situazioni, un'applicazione deve usare il metodo sincrono.
Le transazioni sincrone sono più semplici da gestire e sono più veloci rispetto alle transazioni asincrone. Tuttavia, è possibile eseguire una sola transazione sincrona alla volta, mentre molte transazioni asincrone possono essere eseguite contemporaneamente. Con le transazioni sincrone, un server lento può causare l'inattività di un client mentre è in attesa di una risposta. Inoltre, le transazioni sincrone causano l'immissione di un ciclo modale che potrebbe ignorare il filtro dei messaggi nel ciclo di messaggi dell'applicazione.
Se il client ha installato una routine hook per filtrare i messaggi, ovvero il tipo di hook WH_MSGFILTER in una chiamata alla funzione SetWindowsHookEx , una transazione sincrona non causerà il bypass della routine hook da parte del sistema. Quando si verifica un evento di input mentre il client è in attesa di una transazione sincrona, la routine hook riceve un codice hook MSGF_DDEMGR. Il rischio principale di usare un ciclo modale di transazione sincrono è che un ciclo modale creato da una finestra di dialogo può interferire con l'operazione. Le transazioni asincrone devono essere sempre usate quando il DDEML viene usato da una DLL.
Controllo delle transazioni
Un'applicazione può sospendere le transazioni alla funzione di callback DDE associata a un handle di conversazione specifico o a tutte le transazioni indipendentemente dall'handle di conversazione. Questa funzionalità è utile quando un'applicazione riceve una transazione che richiede un'elaborazione prolungata. In questo caso, l'applicazione può restituire il CBR_BLOCK codice restituito per sospendere le transazioni future associate all'handle di conversazione della transazione, in modo che l'applicazione sia libera di elaborare altre conversazioni.
Al termine dell'elaborazione, l'applicazione chiama la funzione DdeEnableCallback per riprendere le transazioni associate alla conversazione sospesa. Chiamando DdeEnableCallback , DDEML invia nuovamente la transazione che ha causato la sospensione della conversazione da parte dell'applicazione. Pertanto, l'applicazione deve archiviare il risultato della transazione in modo che possa ottenere e restituire il risultato senza rielaborare la transazione.
Un'applicazione può sospendere tutte le transazioni associate a un handle di conversazione specifico specificando l'handle e il flag EC_DISABLE in una chiamata a DdeEnableCallback. Specificando un handle NULL , un'applicazione può sospendere tutte le transazioni per tutte le conversazioni.
Quando una conversazione è stata sospesa, DDEML salva le transazioni per la conversazione in una coda di transazioni. Quando l'applicazione riabilita la conversazione, DDEML rimuove le transazioni salvate dalla coda e passa ogni transazione alla funzione di callback appropriata. La capacità della coda delle transazioni è elevata, ma un'applicazione deve riattivare una conversazione sospesa il prima possibile per evitare di perdere le transazioni.
Un'applicazione può riprendere l'elaborazione normale delle transazioni specificando il flag EC_ENABLEALL in DdeEnableCallback. Per una ripresa più controllata dell'elaborazione delle transazioni, l'applicazione può specificare il flag EC_ENABLEONE. Questo flag rimuove una transazione dalla coda delle transazioni e la passa alla funzione di callback appropriata; dopo l'elaborazione della transazione, tutte le conversazioni vengono nuovamente disabilitate.
Se il flag EC_ENABLEONE e un handle di conversazione vengono specificati nella chiamata a DdeEnableCallback, solo la conversazione viene bloccata dopo l'elaborazione della transazione. Se viene specificato un handle di conversazione NULL , tutte le conversazioni vengono bloccate dopo l'elaborazione di una transazione in qualsiasi conversazione.
Classi di transazione
DDEML ha quattro classi di transazioni. Ogni classe è identificata da una costante che inizia con il prefisso XCLASS_. Le classi vengono definite nel file di intestazione DDEML. Il valore della classe viene combinato con il valore di tipo transazione e viene passato alla funzione di callback DDE dell'applicazione ricevente.
La classe di una transazione determina il valore restituito da una funzione di callback se elabora la transazione. I valori restituiti e i tipi di transazione seguenti sono associati a ognuna delle quattro classi di transazione.
Classe | Valore restituito | Transazione |
---|---|---|
XCLASS_BOOL | TRUE o FAL edizione Standard | XTYP_ADVSTART XTYP_CONNECT |
XCLASS_DATA | Handle dati, CBR_BLOCK codice restituito o NULL | XTYP_ADVREQ XTYP_REQUEST XTYP_WILDCONNECT |
XCLASS_FLAGS | Flag di transazione: DDE_FACK, DDE_FBUSY o DDE_FNOTPROCESedizione Standard D | XTYP_ADVDATA XTYP_EXECUTE XTYP_POKE |
XCLASS_NOTIFICATION | None | XTYP_ADVSTOP XTYP_CONNECT_CONFIRM XTYP_DISCONNECT XTYP_ERROR XTYP_REGISTER XTYP_UNREGISTER XTYP_XACT_COMPLETE |
Natura transazione
Ogni tipo di transazione DDE ha un ricevitore e un'attività associata che determina la generazione di ogni tipo da parte di DDEML.
Tipo di transazione | Destinatario | Causa |
---|---|---|
XTYP_ADVDATA | Client | Un server ha risposto a una transazione XTYP_ADVREQ restituendo un handle dati. |
XTYP_ADVREQ | Server | Un server denominato funzione DdePostAdvise , che indica che il valore di un elemento di dati in un ciclo di consigli è stato modificato. |
XTYP_ADVSTART | Server | Un client ha specificato il tipo di transazione XTYP_ADVSTART in una chiamata alla funzione DdeClientTransaction. |
XTYP_ADVSTOP | Server | Un client ha specificato il tipo di transazione XTYP_ADVSTOP in una chiamata a DdeClientTransaction. |
XTYP_CONNECT | Server | Un client denominato funzione Dde Connessione e ha specificato un nome di servizio e un nome di argomento supportati dal server. |
XTYP_CONNECT_CONFIRM | Server | Il server ha restituito TRUE in risposta a una transazione XTYP_CONNECT o XTYP_WILDCONNECT. |
XTYP_DISCONNECT | Client/Server | Un partner in una conversazione denominata funzione DdeDisconnect , causando la ricezione di questa transazione da parte di entrambi i partner. |
XTYP_ERROR | Client/Server | Si è verificato un errore critico. Il DDEML potrebbe non avere risorse sufficienti per continuare. |
XTYP_EXECUTE | Server | Un client ha specificato il tipo di transazione XTYP_EXECUTE in una chiamata a DdeClientTransaction. |
XTYP_MONITOR | Applicazione di monitoraggio DDE | Si è verificato un evento DDE nel sistema. Per altre informazioni sulle applicazioni di monitoraggio DDE, vedere Monitoraggio delle applicazioni. |
XTYP_POKE | Server | Un client ha specificato il tipo di transazione XTYP_POKE in una chiamata a DdeClientTransaction. |
XTYP_REGISTER | Client/Server | Un'applicazione server ha usato la funzione DdeNameService per registrare un nome di servizio. |
XTYP_REQUEST | Server | Un client ha specificato il tipo di transazione XTYP_REQUEST in una chiamata a DdeClientTransaction. |
XTYP_UNREGISTER | Client/Server | Un'applicazione server usa DdeNameService per annullare la registrazione di un nome di servizio. |
XTYP_WILDCONNECT | Server | Un client denominato funzione Dde Connessione o Dde Connessione List, specificando NULL per il nome del servizio, il nome dell'argomento o entrambi. |
XTYP_XACT_COMPLETE | Client | Una transazione asincrona, inviata quando il client ha specificato il flag TIMEOUT_ASYNC in una chiamata a DdeClientTransaction, ha concluso. |