Gerenciamento de Transações (Troca de Dados)
Depois de estabelecer uma conversa com um servidor, um cliente pode enviar transações para obter dados e serviços do servidor.
Os tópicos a seguir descrevem os tipos de transações que os clientes podem usar para interagir com um servidor.
- Solicitar Transação
- Transação Poke
- Assessorar Transação
- Executar transação
- Transações síncronas e assíncronas
- Controle de Transações
- Classes de transação
- Tipos de transação
Solicitar Transação
Um aplicativo cliente pode usar a transação XTYP_REQUEST para solicitar um item de dados de um aplicativo de servidor. O cliente chama a função DdeClientTransaction, especificando XTYP_REQUEST como o tipo de transação e especificando o item de dados que o aplicativo precisa.
A DDEML (Biblioteca de Gerenciamento de Intercâmbio de Dados Dinâmicos) passa a transação XTYP_REQUEST para o servidor, especificando o nome do tópico, o nome do item e o formato de dados solicitados pelo cliente. Se o servidor oferecer suporte ao tópico, item e formato solicitados, o servidor deverá retornar um identificador de dados que identifique o valor atual do item. O DDEML passa esse identificador para o cliente como o valor de retorno de DdeClientTransaction. O servidor deve retornar NULL se não oferecer suporte ao tópico, item ou formato solicitado.
DdeClientTransaction usa o parâmetro lpdwResult para retornar um sinalizador de status de transação para o cliente. Se o servidor não processar a transação XTYP_REQUEST, DdeClientTransaction retornará NULL e lpdwResult apontará para o sinalizador DDE_FNOTPROCESSED ou DDE_FBUSY. Se o sinalizador DDE_FNOTPROCESSED for retornado, o cliente não poderá determinar por que o servidor não processou a transação.
Se um servidor não oferecer suporte à transação XTYP_REQUEST, ele deverá especificar o sinalizador de filtro CBF_FAIL_REQUESTS na função DdeInitialize. Esse sinalizador impede que o DDEML envie a transação para o servidor.
Transação Poke
Um cliente pode enviar dados não solicitados para um servidor usando DdeClientTransaction para enviar uma transação XTYP_POKE para a função de retorno de chamada de um servidor.
O aplicativo cliente primeiro cria um buffer que contém os dados a serem enviados ao servidor e, em seguida, passa um ponteiro para o buffer como um parâmetro para DdeClientTransaction. Como alternativa, o cliente pode usar a função DdeCreateDataHandle para obter um identificador de dados que identifica os dados e, em seguida, passar o identificador para DdeClientTransaction. Em ambos os casos, o cliente também especifica o nome do tópico, o nome do item e o formato de dados quando chama DdeClientTransaction.
O DDEML passa a transação XTYP_POKE para o servidor, especificando o nome do tópico, o nome do item e o formato de dados que o cliente solicitou. Para aceitar o item de dados e o formato, o servidor deve retornar DDE_FACK. Para rejeitar os dados, o servidor deve retornar DDE_FNOTPROCESSED. Se o servidor estiver muito ocupado para aceitar os dados, o servidor deverá retornar DDE_FBUSY.
Quando DdeClientTransaction retorna, o cliente pode usar o parâmetro lpdwResult para acessar o sinalizador de status da transação. Se o sinalizador estiver DDE_FBUSY, o cliente deverá enviar a transação novamente mais tarde.
Se um servidor não oferecer suporte à transação XTYP_POKE, ele deverá especificar o sinalizador de filtro CBF_FAIL_POKES em DdeInitialize. Esse sinalizador impede que o DDEML envie essa transação para o servidor.
Assessorar Transação
Um aplicativo cliente pode usar o DDEML para estabelecer um ou mais links para itens em um aplicativo de servidor. Quando esse link é estabelecido, o servidor envia atualizações periódicas sobre o item vinculado ao cliente (normalmente, sempre que o valor do item associado ao aplicativo do servidor é alterado). A vinculação estabelece um loop de aconselhamento entre os dois aplicativos que permanece no local até que o cliente o encerre.
Existem dois tipos de ciclos: "quente" e "quente". Em um loop de aviso ativo, o servidor envia imediatamente um identificador de dados que identifica o valor alterado. Em um loop de aviso quente, o servidor notifica o cliente de que o valor do item foi alterado, mas não envia o identificador de dados até que o cliente o solicite.
Um cliente pode solicitar um loop de aviso ativo com um servidor especificando o tipo de transação XTYP_ADVSTART em uma chamada para DdeClientTransaction. Para solicitar um loop de aconselhamento quente, o cliente deve combinar o sinalizador de XTYPF_NODATA com o tipo de transação XTYP_ADVSTART . Em ambos os casos, o DDEML passa a transação XTYP_ADVSTART para a função de retorno de chamada DDE (Dynamic Data Exchange) do servidor. A função de retorno de chamada DDE do servidor deve examinar os parâmetros que acompanham a transação XTYP_ADVSTART (incluindo o formato solicitado, o nome do tópico e o nome do item) e, em seguida, retornar TRUE para permitir que o loop advise ou FALSE negue-o.
Depois que um loop de aconselhamento tiver sido estabelecido, o aplicativo do servidor deve chamar a função DdePostAdvise sempre que o valor do item associado ao nome do item solicitado for alterado. Essa chamada resulta em uma transação XTYP_ADVREQ sendo enviada para a própria função de retorno de chamada DDE do servidor. A função de retorno de chamada DDE do servidor deve retornar um identificador de dados que identifique o novo valor do item de dados. Em seguida, o DDEML notifica o cliente de que o item especificado foi alterado enviando a transação XTYP_ADVDATA para a função de retorno de chamada DDE do cliente.
Se o cliente solicitou um loop de aviso ativo, o DDEML passa o identificador de dados para o item alterado para o cliente durante a transação XTYP_ADVDATA. Caso contrário, o cliente pode enviar uma transação XTYP_REQUEST para obter o identificador de dados.
É possível que um servidor envie atualizações mais rapidamente do que um cliente pode processar os novos dados. A velocidade das atualizações pode ser um problema para um cliente que deve executar longas operações de processamento nos dados. Nesse caso, o cliente deve especificar o sinalizador XTYPF_ACKREQ quando solicitar um loop de aconselhamento. Esse sinalizador faz com que o servidor aguarde até que o cliente reconheça que recebeu e processou um item de dados antes que o servidor envie o próximo item de dados. Os loops de aviso que são estabelecidos com o sinalizador XTYPF_ACKREQ são mais robustos com servidores rápidos, mas podem ocasionalmente perder atualizações. Os loops de aconselhamento estabelecidos sem o sinalizador de XTYPF_ACKREQ têm a garantia de não perder atualizações, desde que o cliente acompanhe o servidor.
Um cliente pode encerrar um loop de aconselhamento especificando o tipo de transação XTYP_ADVSTOP em uma chamada para DdeClientTransaction.
Se um servidor não oferecer suporte a loops de aconselhamento, ele deverá especificar o sinalizador de filtro CBF_FAIL_ADVISES na função DdeInitialize. Esse sinalizador impede que o DDEML envie as transações de XTYP_ADVSTART e XTYP_ADVSTOP para o servidor.
Executar transação
Um cliente pode usar a transação XTYP_EXECUTE para fazer com que um servidor execute um comando ou uma série de comandos.
Para executar um comando de servidor, o cliente primeiro cria um buffer que contém uma cadeia de caracteres de comando para o servidor executar e, em seguida, passa um ponteiro para o buffer ou um identificador de dados identificando o buffer quando ele chama DdeClientTransaction. Outros parâmetros necessários incluem o identificador de conversa, o identificador de cadeia de caracteres do nome do item, a especificação de formato e o tipo de transação XTYP_EXECUTE . Um aplicativo que cria um identificador de dados para passar dados de execução deve especificar NULL para o parâmetro hszItem da função DdeCreateDataHandle e zero para o parâmetro uFmt.
O DDEML passa a transação XTYP_EXECUTE para a função de retorno de chamada DDE do servidor e especifica o nome do formato, o identificador de conversa, o nome do tópico e o identificador de dados que identificam a cadeia de caracteres de comando. Se o servidor oferecer suporte ao comando, ele deverá usar a função DdeAccessData para obter um ponteiro para a cadeia de comando, executar o comando e retornar DDE_FACK. Se o servidor não oferecer suporte ao comando ou não puder concluir a transação, ele deverá retornar DDE_FNOTPROCESSED. O servidor deve retornar DDE_FBUSY se estiver muito ocupado para concluir a transação.
Em geral, a função de retorno de chamada de um servidor deve processar a transação XTYP_EXECUTE antes de retornar com as seguintes exceções:
- Quando o comando passado com a transação XTYP_EXECUTE solicita que o servidor seja encerrado, o servidor não deve encerrar até que sua função de retorno de chamada retorne do processamento de XTYP_EXECUTE.
- Se o servidor precisar executar uma operação, como processar uma caixa de diálogo ou uma transação DDE que possa causar problemas de recursão DDEML, o servidor deverá retornar o código de retorno CBR_BLOCK para bloquear a transação de execução, executar a operação e continuar processando a transação de execução.
Quando DdeClientTransaction retorna, o cliente pode usar o parâmetro lpdwResult para acessar o sinalizador de status da transação. Se o sinalizador estiver DDE_FBUSY, o cliente deverá enviar a transação novamente mais tarde.
Se um servidor não oferecer suporte à transação XTYP_EXECUTE, ele deverá especificar o sinalizador de filtro CBF_FAIL_EXECUTES na função DdeInitialize. Isso impede que o DDEML envie a transação para o servidor.
Transações síncronas e assíncronas
Um cliente pode enviar transações síncronas ou assíncronas. Em uma transação síncrona, o cliente especifica um valor de tempo limite que indica a quantidade máxima de tempo que ele aguardará para que o servidor processe a transação. DdeClientTransaction não retorna até que o servidor processe a transação, a transação falhe ou o valor de tempo limite expire. O cliente especifica o valor de tempo limite quando chama DdeClientTransaction.
Durante uma transação síncrona, o cliente entra em um loop modal enquanto aguarda que a transação seja processada. O cliente ainda pode processar a entrada do usuário, mas não pode enviar outra transação síncrona até que DdeClientTransaction retorne.
Um cliente envia uma transação assíncrona especificando o sinalizador TIMEOUT_ASYNC em DdeClientTransaction. A função retorna após o início da transação, passando um identificador de transação para o cliente. Quando o servidor termina de processar a transação assíncrona, o DDEML envia uma transação XTYP_XACT_COMPLETE para o cliente. Um dos parâmetros que o DDEML passa para o cliente durante a transação XTYP_XACT_COMPLETE é o identificador de transação. Ao comparar esse identificador de transação com o identificador retornado por DdeClientTransaction, o cliente identifica qual transação assíncrona o servidor concluiu o processamento.
Um cliente pode usar a função DdeSetUserHandle como um auxílio no processamento de uma transação assíncrona. Essa função possibilita que um cliente associe um valor definido pelo aplicativo a um identificador de conversa e um identificador de transação. O cliente pode usar a função DdeQueryConvInfo durante a transação XTYP_XACT_COMPLETE para obter o valor definido pelo aplicativo. Devido a essa função, um aplicativo não precisa manter uma lista de identificadores de transação ativos.
Quando um cliente conclui com êxito uma solicitação de dados usando uma transação síncrona, o DDEML não tem como saber quando o cliente terminou de usar os dados recebidos. O aplicativo cliente deve passar o identificador de dados recebido para a função DdeFreeDataHandle , notificando o DDEML de que o identificador não será mais usado. Os identificadores de dados retornados por transações síncronas são efetivamente de propriedade do cliente.
Se um servidor não processar uma transação assíncrona em tempo hábil, o cliente poderá abandonar a transação chamando a função DdeAbandonTransaction. O DDEML libera todos os recursos associados à transação e descarta os resultados da transação quando o servidor termina de processá-la. Um tempo limite durante uma transação síncrona efetivamente cancela a transação.
O método de transação assíncrona é fornecido para aplicativos que devem enviar um alto volume de transações DDE e, ao mesmo tempo, executar uma quantidade substancial de processamento, como executar cálculos. O método assíncrono também é útil em aplicativos que devem parar de processar transações DDE temporariamente para que possam concluir outras tarefas sem interrupção. Na maioria das outras situações, um aplicativo deve usar o método síncrono.
As transações síncronas são mais simples de manter e são mais rápidas do que as transações assíncronas. No entanto, apenas uma transação síncrona pode ser executada por vez, enquanto muitas transações assíncronas podem ser executadas simultaneamente. Com transações síncronas, um servidor lento pode fazer com que um cliente permaneça ocioso enquanto aguarda uma resposta. Além disso, as transações síncronas fazem com que o cliente insira um loop modal que pode ignorar a filtragem de mensagens no próprio loop de mensagens do aplicativo.
Se o cliente tiver instalado um procedimento de gancho para filtrar mensagens (ou seja, especificado o tipo de gancho WH_MSGFILTER em uma chamada para a função SetWindowsHookEx ), uma transação síncrona não fará com que o sistema ignore o procedimento de gancho. Quando um evento de entrada ocorre enquanto o cliente aguarda o término de uma transação síncrona, o procedimento de gancho recebe um código de gancho MSGF_DDEMGR. O principal perigo de usar um loop modal de transação síncrona é que um loop modal criado por uma caixa de diálogo pode interferir em sua operação. Transações assíncronas sempre devem ser usadas quando o DDEML está sendo usado por uma DLL.
Controle de Transações
Um aplicativo pode suspender as transações para sua função de retorno de chamada DDE ou aquelas transações associadas a um identificador de conversa específico ou todas as transações, independentemente do identificador de conversa. Esse recurso é útil quando um aplicativo recebe uma transação que requer processamento demorado. Nesse caso, o aplicativo pode retornar o código de retorno do CBR_BLOCK para suspender transações futuras associadas ao identificador de conversa da transação, para que o aplicativo fique livre para processar outras conversas.
Quando o processamento for concluído, o aplicativo chamará a função DdeEnableCallback para retomar as transações associadas à conversa suspensa. Chamar DdeEnableCallback faz com que o DDEML reenvie a transação que resultou na suspensão da conversa pelo aplicativo. Portanto, o aplicativo deve armazenar o resultado da transação de tal forma que possa obter e retornar o resultado sem reprocessar a transação.
Um aplicativo pode suspender todas as transações associadas a um identificador de conversa específico especificando o identificador e o sinalizador EC_DISABLE em uma chamada para DdeEnableCallback. Ao especificar um identificador NULL, um aplicativo pode suspender todas as transações de todas as conversas.
Quando uma conversa é suspensa, o DDEML salva transações para a conversa em uma fila de transações. Quando o aplicativo reativa a conversa, o DDEML remove as transações salvas da fila e passa cada transação para a função de retorno de chamada apropriada. A capacidade da fila de transações é grande, mas um aplicativo deve reativar uma conversa suspensa o mais rápido possível para evitar a perda de transações.
Um aplicativo pode retomar o processamento de transações usuais especificando o sinalizador EC_ENABLEALL em DdeEnableCallback. Para uma retomada mais controlada do processamento de transações, o aplicativo pode especificar o sinalizador EC_ENABLEONE. Esse sinalizador remove uma transação da fila de transações e a passa para a função de retorno de chamada apropriada; Depois que essa transação for processada, todas as conversas serão novamente desativadas.
Se o sinalizador de EC_ENABLEONE e um identificador de conversa forem especificados na chamada para DdeEnableCallback, somente essa conversa será bloqueada após a transação ter sido processada. Se um identificador de conversa NULL for especificado, todas as conversas serão bloqueadas depois que uma transação for processada em qualquer conversa.
Classes de Transação
O DDEML tem quatro classes de transações. Cada classe é identificada por uma constante que começa com o prefixo XCLASS_. As classes são definidas no arquivo de cabeçalho DDEML. O valor da classe é combinado com o valor do tipo de transação e é passado para a função de retorno de chamada DDE do aplicativo de recebimento.
A classe de uma transação determina o valor de retorno que uma função de retorno de chamada deve retornar se processar a transação. Os seguintes valores de retorno e tipos de transação estão associados a cada uma das quatro classes de transação.
Classe | Valor retornado | Transação |
---|---|---|
XCLASS_BOOL | VERDADEIRO ou FALSO | XTYP_ADVSTART XTYP_CONNECT |
XCLASS_DATA | Um identificador de dados, o código de retorno CBR_BLOCK ou NULL | XTYP_ADVREQ XTYP_REQUEST XTYP_WILDCONNECT |
XCLASS_FLAGS | Um sinalizador de transação: DDE_FACK, DDE_FBUSY ou DDE_FNOTPROCESSED | XTYP_ADVDATA XTYP_EXECUTE XTYP_POKE |
XCLASS_NOTIFICATION | Nenhum | XTYP_ADVSTOP XTYP_CONNECT_CONFIRM XTYP_DISCONNECT XTYP_ERROR XTYP_REGISTER XTYP_UNREGISTER XTYP_XACT_COMPLETE |
Tipos de Transação
Cada tipo de transação DDE tem um receptor e uma atividade associada que faz com que o DDEML gere cada tipo.
Tipo de transação | Receptor | Causa |
---|---|---|
XTYP_ADVDATA | Cliente | Um servidor respondeu a uma transação XTYP_ADVREQ retornando um identificador de dados. |
XTYP_ADVREQ | Servidor | Um servidor chamado a função DdePostAdvise indica que o valor de um item de dados em um loop advise foi alterado. |
XTYP_ADVSTART | Servidor | Um cliente especificou o tipo de transação XTYP_ADVSTART em uma chamada para a função DdeClientTransaction. |
XTYP_ADVSTOP | Servidor | Um cliente especificou o tipo de transação XTYP_ADVSTOP em uma chamada para DdeClientTransaction. |
XTYP_CONNECT | Servidor | Um cliente chamou a função DdeConnect e especificou um nome de serviço e um nome de tópico suportados pelo servidor. |
XTYP_CONNECT_CONFIRM | Servidor | O servidor retornou TRUE em resposta a uma transação XTYP_CONNECT ou XTYP_WILDCONNECT . |
XTYP_DISCONNECT | Cliente/Servidor | Um parceiro em uma conversa chamada função DdeDisconnect , fazendo com que ambos os parceiros recebam essa transação. |
XTYP_ERROR | Cliente/Servidor | Ocorreu um erro crítico. O DDEML pode não ter recursos suficientes para continuar. |
XTYP_EXECUTE | Servidor | Um cliente especificou o tipo de transação XTYP_EXECUTE em uma chamada para DdeClientTransaction. |
XTYP_MONITOR | Aplicativo de monitoramento DDE | Ocorreu um evento DDE no sistema. Para obter mais informações sobre aplicativos de monitoramento DDE, consulte Monitorando aplicativos. |
XTYP_POKE | Servidor | Um cliente especificou o tipo de transação XTYP_POKE em uma chamada para DdeClientTransaction. |
XTYP_REGISTER | Cliente/Servidor | Um aplicativo de servidor usou a função DdeNameService para registrar um nome de serviço. |
XTYP_REQUEST | Servidor | Um cliente especificou o tipo de transação XTYP_REQUEST em uma chamada para DdeClientTransaction. |
XTYP_UNREGISTER | Cliente/Servidor | Um aplicativo de servidor usou DdeNameService para cancelar o registro de um nome de serviço. |
XTYP_WILDCONNECT | Servidor | Um cliente chamou a função DdeConnect ou DdeConnectList, especificando NULL para o nome do serviço, o nome do tópico ou ambos. |
XTYP_XACT_COMPLETE | Cliente | Uma transação assíncrona, enviada quando o cliente especificou o sinalizador TIMEOUT_ASYNC em uma chamada para DdeClientTransaction, foi concluída. |