Поделиться через


Управление транзакциями (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, он должен указать флаг фильтра CBF_FAIL_REQUESTS в функции DdeInitialize. Этот флаг запрещает DDEML отправлять транзакцию на сервер.

Транзакция Poke

Клиент может отправлять незапрошенные данные на сервер с помощью DdeClientTransaction для отправки транзакции XTYP_POKE функции обратного вызова сервера.

Клиентское приложение сначала создает буфер, содержащий данные для отправки на сервер, а затем передает указатель на буфер в качестве параметра в DdeClientTransaction. Кроме того, клиент может использовать функцию DdeCreateDataHandle для получения дескриптора данных, который идентифицирует данные, а затем передает дескриптор DdeClientTransaction. В любом случае клиент также указывает имя раздела, имя элемента и формат данных при вызове DdeClientTransaction.

DDEML передает транзакцию XTYP_POKE серверу, указав имя раздела, имя элемента и формат данных, запрошенный клиентом. Чтобы принять элемент данных и формат, сервер должен вернуть DDE_FACK. Чтобы отклонить данные, сервер должен вернуть DDE_FNOTPROCESSED. Если сервер слишком занят, чтобы принять данные, сервер должен вернуть DDE_FBUSY.

При возврате DdeClientTransaction клиент может использовать параметр lpdwResult для доступа к флагу состояния транзакции. Если флаг DDE_FBUSY, клиент должен снова отправить транзакцию позже.

Если сервер не поддерживает транзакцию XTYP_POKE, он должен указать флаг фильтра CBF_FAIL_POKES в DdeInitialize. Этот флаг запрещает DDEML отправлять эту транзакцию на сервер.

Советная транзакция

Клиентское приложение может использовать DDEML для установления одной или нескольких ссылок на элементы в серверном приложении. При установке такой ссылки сервер отправляет периодические обновления связанного элемента клиенту (как правило, при изменении значения элемента, связанного с серверным приложением). Связывание устанавливает цикл консультаций между двумя приложениями, которые остаются на месте, пока клиент не завершит его.

Существует два типа циклов советов: "горячий" и "теплый". В цикле горячего консультирования сервер немедленно отправляет дескриптор данных, определяющий измененное значение. В цикле теплых консультаций сервер уведомляет клиента о том, что значение элемента изменилось, но не отправляет дескриптор данных до тех пор, пока клиент не запрашивает его.

Клиент может запросить цикл горячего консультирования с сервером, указав тип транзакции XTYP_ADVSTART в вызове DdeClientTransaction. Чтобы запросить цикл теплых рекомендаций, клиент должен объединить флаг 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, гарантированно не пропускают обновления до тех пор, пока клиент продолжает работать с сервером.

Клиент может завершить цикл консультаций, указав тип транзакции XTYP_ADVSTOP в вызове DdeClientTransaction.

Если сервер не поддерживает циклы рекомендаций, он должен указать флаг фильтра CBF_FAIL_ADVISES в функции DdeInitialize. Этот флаг запрещает DDEML отправлять XTYP_ADVSTART и XTYP_ADVSTOP транзакции на сервер.

Выполнение транзакции

Клиент может использовать транзакцию XTYP_EXECUTE , чтобы сервер выполнял команду или серию команд.

Чтобы выполнить команду сервера, клиент сначала создает буфер, содержащий строку команды для выполнения сервера, а затем передает указатель на буфер или дескриптор данных, определяющий буфер при вызове DdeClientTransaction. Другие необходимые параметры включают дескриптор беседы, дескриптор строки имени элемента, спецификацию формата и тип транзакции XTYP_EXECUTE . Приложение, создающее дескриптор данных для передачи данных, должно указывать значение NULL для параметра hszItem функции DdeCreateDataHandle и ноль для параметра uFmt.

DDEML передает транзакцию XTYP_EXECUTE функции обратного вызова DDE сервера и указывает имя формата, дескриптор беседы, имя раздела и дескриптор данных, определяющий командную строку. Если сервер поддерживает команду, он должен использовать функцию DdeAccessData для получения указателя на строку команды, выполнения команды и возврата DDE_FACK. Если сервер не поддерживает команду или не может завершить транзакцию, он должен вернуть DDE_FNOTPROCESSED. Сервер должен вернуть DDE_FBUSY, если он слишком занят, чтобы завершить транзакцию.

Как правило, функция обратного вызова сервера должна обрабатывать транзакцию XTYP_EXECUTE перед возвратом со следующими исключениями:

  1. Когда команда, переданная с XTYP_EXECUTE транзакцией, запрашивает завершение работы сервера, сервер не должен завершаться до тех пор, пока ее функция обратного вызова не возвращается из обработки XTYP_EXECUTE.
  2. Если сервер должен выполнить операцию, например обработку диалогового окна или транзакции DDE, которая может вызвать проблемы рекурсии DDEML, сервер должен вернуть CBR_BLOCK возвращаемый код, чтобы заблокировать транзакцию выполнения, выполнить операцию, а затем возобновить обработку транзакции выполнения.

При возврате DdeClientTransaction клиент может использовать параметр lpdwResult для доступа к флагу состояния транзакции. Если флаг DDE_FBUSY, клиент должен снова отправить транзакцию позже.

Если сервер не поддерживает транзакцию XTYP_EXECUTE, он должен указать флаг фильтра CBF_FAIL_EXECUTES в функции DdeInitialize. Это предотвращает отправку транзакции на сервер DDEML.

Синхронные и асинхронные транзакции

Клиент может отправлять синхронные или асинхронные транзакции. В синхронной транзакции клиент задает значение времени ожидания, указывающее максимальное время, которое будет ожидать, пока сервер будет обрабатывать транзакцию. DdeClientTransaction не возвращается до тех пор, пока сервер не обрабатывает транзакцию, транзакция завершается сбоем или истекает время ожидания. Клиент задает значение времени ожидания при вызове DdeClientTransaction.

Во время синхронной транзакции клиент вводит модальный цикл во время ожидания обработки транзакции. Клиент по-прежнему может обрабатывать входные данные пользователя, но не может отправлять другую синхронную транзакцию до возврата DdeClientTransaction.

Клиент отправляет асинхронную транзакцию, указав флаг TIMEOUT_ASYNC в DdeClientTransaction. Функция возвращается после начала транзакции, передав идентификатор транзакции клиенту. Когда сервер завершит обработку асинхронной транзакции, DDEML отправляет XTYP_XACT_COMPLETE транзакцию клиенту. Одним из параметров, передаваемых DDEML клиенту во время XTYP_XACT_COMPLETE транзакции, является идентификатор транзакции. Сравнивая этот идентификатор транзакции с идентификатором , возвращаемым DdeClientTransaction, клиент определяет асинхронную транзакцию, которую сервер завершил обработку.

Клиент может использовать функцию DdeSetUserHandle в качестве помощи в обработке асинхронной транзакции. Эта функция позволяет клиенту связать определенное приложением значение с дескриптором беседы и идентификатором транзакции. Клиент может использовать функцию DdeQueryConvInfo во время транзакции XTYP_XACT_COMPLETE для получения определенного приложением значения. Из-за этой функции приложению не требуется поддерживать список активных идентификаторов транзакций.

Когда клиент успешно завершает запрос данных с помощью синхронной транзакции, DDEML не может сообщить, когда клиент завершит работу с полученными данными. Клиентское приложение должно передать дескриптор данных, полученный функции DdeFreeDataHandle , уведомляя DDEML о том, что дескриптор больше не будет использоваться. Дескриптора данных, возвращаемые синхронными транзакциями, фактически принадлежат клиенту.

Если сервер не обрабатывает асинхронную транзакцию своевременно, клиент может отказаться от транзакции, вызвав функцию DdeAbandonTransaction. DDEML освобождает все ресурсы, связанные с транзакцией, и отсоединяет карта результаты транзакции, когда сервер завершит обработку. Время ожидания во время синхронной транзакции фактически отменяет транзакцию.

Метод асинхронной транзакции предоставляется для приложений, которые должны отправлять большой объем транзакций DDE, одновременно выполняя значительный объем обработки, например выполнение вычислений. Асинхронный метод также полезен в приложениях, которые должны временно прекратить обработку транзакций DDE, чтобы они могли выполнять другие задачи без прерывания. В большинстве других ситуаций приложение должно использовать синхронный метод.

Синхронные транзакции проще поддерживать и быстрее, чем асинхронные транзакции. Однако одновременно можно выполнять только одну синхронную транзакцию, в то время как многие асинхронные транзакции могут выполняться одновременно. При синхронных транзакциях медленный сервер может привести к тому, что клиент остается бездействующих во время ожидания ответа. Кроме того, синхронные транзакции приводят к тому, что клиент вводит модальный цикл, который может обойти фильтрацию сообщений в собственном цикле сообщений приложения.

Если клиент установил процедуру перехватчика для фильтрации сообщений (то есть указал тип WH_MSGFILTER перехватчика в вызове функции SetWindowsHookEx ), синхронная транзакция не приведет к обходу процедуры перехватчика. Когда происходит входное событие, пока клиент ожидает синхронной транзакции, процедура перехватчика получает код перехватчика MSGF_DDEMGR. Основная опасность использования модального цикла синхронной транзакции заключается в том, что модальный цикл, созданный диалогом, может препятствовать его работе. Асинхронные транзакции всегда следует использовать при использовании DDEML библиотекой DLL.

Управление транзакцией

Приложение может приостановить транзакции в функции обратного вызова DDE либо эти транзакции, связанные с определенным дескриптором беседы, либо всеми транзакциями независимо от дескриптора беседы. Эта возможность полезна, если приложение получает транзакцию, требующую длительной обработки. В таком случае приложение может вернуть CBR_BLOCK возвращать код для приостановки будущих транзакций, связанных с дескриптором беседы транзакции, чтобы приложение было свободно обрабатывать другие беседы.

После завершения обработки приложение вызывает функцию DdeEnableCallback для возобновления транзакций, связанных с приостановленной беседой. Вызов DdeEnableCallback приводит к повторной отправке транзакции DDEML, которая привела к приостановке беседы приложением. Поэтому приложение должно хранить результат транзакции таким образом, чтобы он смог получить и вернуть результат без повторной обработки транзакции.

Приложение может приостановить все транзакции, связанные с определенным дескриптором беседы, указав дескриптор и флаг EC_DISABLE в вызове DdeEnableCallback. Указав дескриптор NULL , приложение может приостановить все транзакции для всех бесед.

При приостановке беседы DDEML сохраняет транзакции для беседы в очереди транзакций. Когда приложение повторно записывает беседу, DDEML удаляет сохраненные транзакции из очереди и передает каждую транзакцию соответствующей функции обратного вызова. Емкость очереди транзакций велика, но приложение должно повторно создать приостановленную беседу как можно скорее, чтобы избежать потери транзакций.

Приложение может возобновить обычную обработку транзакций, указав флаг EC_ENABLEALL в DdeEnableCallback. Для более контролируемого возобновления обработки транзакций приложение может указать флаг EC_ENABLEONE. Этот флаг удаляет одну транзакцию из очереди транзакций и передает ее в соответствующую функцию обратного вызова; После обработки этой транзакции все беседы снова отключены.

Если флаг EC_ENABLEONE и дескриптор беседы указаны в вызове DdeEnableCallback, то после обработки транзакции будет заблокирована только эта беседа. Если указан дескриптор бесед NULL, все беседы блокируются после обработки транзакции в любой беседе.

Классы проводок

DDEML имеет четыре класса транзакций. Каждый класс определяется константой, начинающейся с префикса XCLASS_. Классы определены в файле заголовка DDEML. Значение класса объединяется со значением типа транзакции и передается функции обратного вызова DDE принимающего приложения.

Класс транзакции определяет возвращаемое значение, возвращаемое функцией обратного вызова, если она обрабатывает транзакцию. Следующие возвращаемые значения и типы транзакций связаны с каждым из четырех классов транзакций.

Класс Возвращаемое значение Транзакция
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 Сервер Клиент указал тип транзакции XTYP_ADVSTART в вызове функции DdeClientTransaction.
XTYP_ADVSTOP Сервер Клиент указал тип транзакции XTYP_ADVSTOP в вызове DdeClientTransaction.
XTYP_CONNECT Сервер Клиент называется функцией Dde Подключение и указывает имя службы и имя раздела, поддерживаемые сервером.
XTYP_CONNECT_CONFIRM Сервер Сервер вернул значение TRUE в ответ на XTYP_CONNECT или XTYP_WILDCONNECT транзакцию.
XTYP_DISCONNECT Клиентская/серверная библиотека Партнер в беседе с именем функции DdeDisconnect , что приводит к получению этой транзакции обоими партнерами.
XTYP_ERROR Клиентская/серверная библиотека Произошла критическая ошибка. DDEML может не иметь достаточных ресурсов для продолжения.
XTYP_EXECUTE Сервер Клиент указал тип транзакции XTYP_EXECUTE в вызове DdeClientTransaction.
XTYP_MONITOR Приложение мониторинга DDE Событие DDE произошло в системе. Дополнительные сведения о приложениях мониторинга DDE см. в разделе "Мониторинг приложений".
XTYP_POKE Сервер Клиент указал тип транзакции XTYP_POKE в вызове DdeClientTransaction.
XTYP_REGISTER Клиентская/серверная библиотека Серверное приложение использовало функцию DdeNameService для регистрации имени службы.
XTYP_REQUEST Сервер Клиент указал тип транзакции XTYP_REQUEST в вызове DdeClientTransaction.
XTYP_UNREGISTER Клиентская/серверная библиотека Серверное приложение использовало DdeNameService для отмены регистрации имени службы.
XTYP_WILDCONNECT Сервер Клиент, называемый функцией Dde Подключение или Dde Подключение List, указав ЗНАЧЕНИЕ NULL для имени службы, имени раздела или обоих.
XTYP_XACT_COMPLETE Клиент Асинхронная транзакция, отправленная, когда клиент указал флаг TIMEOUT_ASYNC в вызове DdeClientTransaction, завершился.