Udostępnij przez


Zarządzanie transakcjami (Wymiana danych)

Po nawiązaniu rozmowy z serwerem klient może wysyłać transakcje w celu uzyskania danych i usług z serwera.

W poniższych tematach opisano typy transakcji, których klienci mogą używać do interakcji z serwerem.

Żądanie transakcji

Aplikacja kliencka może użyć transakcji XTYP_REQUEST, aby zażądać elementu danych z aplikacji serwera. Klient wywołuje funkcję DdeClientTransaction, określając XTYP_REQUEST jako typ transakcji i określając element danych wymagany przez aplikację.

Biblioteka dynamicznego zarządzania exchange danych (DDEML) przekazuje transakcję XTYP_REQUEST do serwera, określając nazwę tematu, nazwę elementu i format danych żądany przez klienta. Jeśli serwer obsługuje żądany temat, element i format, serwer powinien zwrócić uchwyt danych, który identyfikuje bieżącą wartość elementu. DDEML przekazuje ten uchwyt do klienta jako wartość zwracaną z DdeClientTransaction. Serwer powinien zwrócić null, jeśli nie obsługuje tematu, elementu lub żądanego formatu.

DdeClientTransaction używa parametru lpdwResult, aby zwrócić flagę stanu transakcji do klienta. Jeśli serwer nie przetwarza transakcji XTYP_REQUEST, DdeClientTransaction zwraca null, a lpdwResult wskazuje flagę DDE_FNOTPROCESSED lub DDE_FBUSY. Jeśli zostanie zwrócona flaga DDE_FNOTPROCESSED, klient nie może określić, dlaczego serwer nie przetworzył transakcji.

Jeśli serwer nie obsługuje transakcji XTYP_REQUEST, powinien określić flagę filtru CBF_FAIL_REQUESTS w funkcji DdeInitialize. Ta flaga uniemożliwia DDEML wysyłanie transakcji do serwera.

Transakcja poke

Klient może wysyłać niepożądane dane do serwera przy użyciu DdeClientTransaction wysłać transakcję XTYP_POKE do funkcji wywołania zwrotnego serwera.

Aplikacja kliencka najpierw tworzy bufor zawierający dane wysyłane do serwera, a następnie przekazuje wskaźnik do buforu jako parametr do DdeClientTransaction. Alternatywnie klient może użyć funkcji DdeCreateDataHandle, aby uzyskać uchwyt danych, który identyfikuje dane, a następnie przekazać dojście do DdeClientTransaction. W obu przypadkach klient określa również nazwę tematu, nazwę elementu i format danych, gdy wywołuje DdeClientTransaction.

DDEML przekazuje transakcję XTYP_POKE do serwera, określając nazwę tematu, nazwę elementu i format danych, którego zażądał klient. Aby zaakceptować element danych i format, serwer powinien zwrócić DDE_FACK. Aby odrzucić dane, serwer powinien zwrócić DDE_FNOTPROCESSED. Jeśli serwer jest zbyt zajęty, aby zaakceptować dane, serwer powinien zwrócić DDE_FBUSY.

Gdy zwraca DdeClientTransaction, klient może użyć parametru lpdwResult, aby uzyskać dostęp do flagi stanu transakcji. Jeśli flaga jest DDE_FBUSY, klient powinien wysłać transakcję ponownie później.

Jeśli serwer nie obsługuje transakcji XTYP_POKE, powinien określić flagę filtru CBF_FAIL_POKES w DdeInitialize. Ta flaga uniemożliwia DDEML wysyłanie tej transakcji do serwera.

Doradzanie transakcji

Aplikacja kliencka może używać DDEML do ustanowienia co najmniej jednego łącza do elementów w aplikacji serwera. Po ustanowieniu takiego linku serwer wysyła okresowe aktualizacje dotyczące połączonego elementu do klienta (zazwyczaj za każdym razem, gdy wartość elementu skojarzonego z aplikacją serwera ulegnie zmianie). Łączenie ustanawia pętlę doradcy między dwiema aplikacjami, które pozostają w miejscu do momentu jego zakończenia.

Istnieją dwa rodzaje pętli porad: "gorące" i "ciepłe". W pętli gorącej doradcy serwer natychmiast wysyła uchwyt danych, który identyfikuje zmienioną wartość. W ciepłej pętli porad serwer powiadamia klienta, że wartość elementu uległa zmianie, ale nie wysyła dojścia danych do momentu, gdy klient zażąda go.

Klient może zażądać pętli gorącej porady z serwerem, określając typ transakcji XTYP_ADVSTART w wywołaniu DdeClientTransaction. Aby zażądać ciepłej pętli porad, klient musi połączyć flagę XTYPF_NODATA z typem transakcji XTYP_ADVSTART. W obu zdarzeniach DDEML przekazuje transakcję XTYP_ADVSTART do funkcji wywołania zwrotnego dynamicznej wymiany danych (DDE) serwera. Funkcja wywołania zwrotnego DDE serwera powinna zbadać parametry, które towarzyszą transakcji XTYP_ADVSTART (w tym żądanego formatu, nazwy tematu i nazwy elementu), a następnie zwrócić true, aby umożliwić pętli doradcy lub FALSE go odrzucić.

Po ustanowieniu pętli doradcy aplikacja serwera powinna wywołać funkcję DdePostAdvise za każdym razem, gdy wartość elementu skojarzonego z żądaną nazwą elementu ulegnie zmianie. To wywołanie powoduje wysłanie transakcji XTYP_ADVREQ do własnej funkcji wywołania zwrotnego DDE serwera. Funkcja wywołania zwrotnego DDE serwera powinna zwrócić uchwyt danych, który identyfikuje nową wartość elementu danych. Następnie DDEML powiadamia klienta, że określony element został zmieniony przez wysłanie transakcji XTYP_ADVDATA do funkcji wywołania zwrotnego DDE klienta.

Jeśli klient zażądał pętli porady na gorąco, DDEML przekazuje dojście danych do zmienionego elementu do klienta podczas transakcji XTYP_ADVDATA. W przeciwnym razie klient może wysłać transakcję XTYP_REQUEST w celu uzyskania dojścia danych.

Serwer może wysyłać aktualizacje szybciej niż klient może przetwarzać nowe dane. Szybkość aktualizacji może być problemem dla klienta, który musi wykonywać długotrwałe operacje przetwarzania danych. W takim przypadku klient powinien określić flagę XTYPF_ACKREQ, gdy żąda pętli porad. Ta flaga powoduje, że serwer czeka, aż klient potwierdzi, że odebrał i przetworzył element danych przed wysłaniem następnego elementu danych przez serwer. Pętle doradcy ustanowione za pomocą flagi XTYPF_ACKREQ są bardziej niezawodne w przypadku szybkich serwerów, ale czasami mogą przegapić aktualizacje. Pętle doradcy ustanowione bez flagi XTYPF_ACKREQ nie mają gwarancji, że nie przegapić aktualizacji tak długo, jak klient utrzymuje się z serwerem.

Klient może zakończyć pętlę porad, określając typ transakcji XTYP_ADVSTOP w wywołaniu DdeClientTransaction.

Jeśli serwer nie obsługuje pętli porad, powinien określić flagę filtru CBF_FAIL_ADVISES w funkcji DdeInitialize. Ta flaga uniemożliwia DDEML wysyłanie XTYP_ADVSTART i XTYP_ADVSTOP transakcji do serwera.

Wykonywanie transakcji

Klient może użyć transakcji XTYP_EXECUTE, aby spowodować, że serwer wykona polecenie lub serię poleceń.

Aby wykonać polecenie serwera, klient najpierw tworzy bufor zawierający ciąg polecenia dla serwera do wykonania, a następnie przekazuje wskaźnik do buforu lub uchwyt danych identyfikujący bufor, gdy wywołuje DdeClientTransaction. Inne wymagane parametry obejmują dojście do konwersacji, uchwyt ciągu nazwy elementu, specyfikację formatu i typ transakcji XTYP_EXECUTE. Aplikacja, która tworzy dojście danych do przekazywania danych wykonywania, musi określić null dla parametru hszItem funkcji DdeCreateDataHandle i zera dla parametru uFmt.

DDEML przekazuje transakcję XTYP_EXECUTE do funkcji wywołania zwrotnego DDE serwera i określa nazwę formatu, uchwyt konwersacji, nazwę tematu i uchwyt danych identyfikujący ciąg polecenia. Jeśli serwer obsługuje polecenie, powinien użyć funkcji DdeAccessData, aby uzyskać wskaźnik do ciągu polecenia, wykonać polecenie, a następnie zwrócić DDE_FACK. Jeśli serwer nie obsługuje polecenia lub nie może ukończyć transakcji, powinien zwrócić DDE_FNOTPROCESSED. Serwer powinien zwrócić DDE_FBUSY, jeśli jest zbyt zajęty, aby ukończyć transakcję.

Ogólnie rzecz biorąc, funkcja wywołania zwrotnego serwera powinna przetwarzać transakcję XTYP_EXECUTE przed zwróceniem z następującymi wyjątkami:

  1. Gdy polecenie przekazane za pomocą transakcji XTYP_EXECUTE żąda zakończenia serwera, serwer nie powinien zakończyć, dopóki funkcja wywołania zwrotnego nie powróci z przetwarzania XTYP_EXECUTE.
  2. Jeśli serwer musi wykonać operację, taką jak przetwarzanie okna dialogowego lub transakcji DDE, która może powodować problemy z rekursją DDEML, serwer powinien zwrócić CBR_BLOCK zwracać kod, aby zablokować wykonaną transakcję, wykonać operację, a następnie wznowić przetwarzanie transakcji wykonania.

Gdy zwraca DdeClientTransaction, klient może użyć parametru lpdwResult, aby uzyskać dostęp do flagi stanu transakcji. Jeśli flaga jest DDE_FBUSY, klient powinien wysłać transakcję ponownie później.

Jeśli serwer nie obsługuje transakcji XTYP_EXECUTE, powinien określić flagę filtru CBF_FAIL_EXECUTES w funkcji DdeInitialize. Uniemożliwia to DDEML wysyłanie transakcji do serwera.

Transakcje synchroniczne i asynchroniczne

Klient może wysyłać transakcje synchroniczne lub asynchroniczne. W transakcji synchronicznej klient określa wartość limitu czasu, która wskazuje maksymalny czas oczekiwania na przetworzenie transakcji przez serwer. DdeClientTransaction nie zostanie zwrócona, dopóki serwer nie przetworzy transakcji, transakcja zakończy się niepowodzeniem lub wygaśnie wartość limitu czasu. Klient określa wartość limitu czasu, gdy wywołuje DdeClientTransaction.

Podczas transakcji synchronicznej klient wprowadza pętlę modalną podczas oczekiwania na przetworzenie transakcji. Klient może nadal przetwarzać dane wejściowe użytkownika, ale nie może wysłać innej transakcji synchronicznej, dopóki nie zostanie zwrócona DdeClientTransaction.

Klient wysyła transakcję asynchroniczną, określając flagę TIMEOUT_ASYNC w DdeClientTransaction. Funkcja zwraca wartość po rozpoczęciu transakcji, przekazując identyfikator transakcji do klienta. Po zakończeniu przetwarzania transakcji asynchronicznej serwer DDEML wysyła XTYP_XACT_COMPLETE transakcji do klienta. Jednym z parametrów, które DDEML przekazuje do klienta podczas transakcji XTYP_XACT_COMPLETE jest identyfikator transakcji. Porównując ten identyfikator transakcji z identyfikatorem zwróconym przez DdeClientTransaction, klient identyfikuje, która asynchroniczna transakcja serwera zakończyła przetwarzanie.

Klient może użyć funkcji DdeSetUserHandle jako pomocy w przetwarzaniu transakcji asynchronicznej. Ta funkcja umożliwia klientowi skojarzenie wartości zdefiniowanej przez aplikację z uchwytem konwersacji i identyfikatorem transakcji. Klient może użyć funkcji DdeQueryConvInfo podczas transakcji XTYP_XACT_COMPLETE w celu uzyskania wartości zdefiniowanej przez aplikację. Ze względu na tę funkcję aplikacja nie musi utrzymywać listy aktywnych identyfikatorów transakcji.

Gdy klient pomyślnie ukończy żądanie dotyczące danych przy użyciu transakcji synchronicznej, DDEML nie ma możliwości powiadomienia, kiedy klient zakończył korzystanie z odebranych danych. Aplikacja kliencka musi przekazać dojście danych odebrane do funkcjiDdeFreeDataHandle, powiadamiając DDEML, że dojście nie będzie już używane. Obsługa danych zwracana przez transakcje synchroniczne jest skutecznie własnością klienta.

Jeśli serwer nie przetwarza transakcji asynchronicznej w odpowiednim czasie, klient może porzucić transakcję, wywołując funkcję DdeAbandonTransaction. DDEML zwalnia wszystkie zasoby skojarzone z transakcją i odrzuca wyniki transakcji po zakończeniu przetwarzania go przez serwer. Limit czasu podczas transakcji synchronicznej skutecznie anuluje transakcję.

Metoda transakcji asynchronicznej jest udostępniana dla aplikacji, które muszą wysyłać dużą liczbę transakcji DDE podczas jednoczesnego wykonywania znacznej ilości przetwarzania, takich jak wykonywanie obliczeń. Metoda asynchroniczna jest również przydatna w aplikacjach, które muszą tymczasowo zatrzymać przetwarzanie transakcji DDE, aby mogły wykonywać inne zadania bez przerwy. W większości innych sytuacji aplikacja powinna używać metody synchronicznej.

Transakcje synchroniczne są prostsze w obsłudze i są szybsze niż transakcje asynchroniczne. Jednak tylko jedna transakcja synchroniczna może być wykonywana jednocześnie, podczas gdy wiele transakcji asynchronicznych można wykonywać jednocześnie. W przypadku transakcji synchronicznych powolny serwer może spowodować, że klient pozostanie bezczynny, czekając na odpowiedź. Ponadto transakcje synchroniczne powodują, że klient wprowadza modalną pętlę, która może pominąć filtrowanie komunikatów we własnej pętli komunikatów aplikacji.

Jeśli klient zainstalował procedurę zaczepienia w celu filtrowania komunikatów (tj. określono typ haka WH_MSGFILTER w wywołaniu funkcji SetWindowsHookEx), transakcja synchroniczna nie spowoduje obejścia procedury haka przez system. Gdy zdarzenie wejściowe występuje, gdy klient oczekuje na zakończenie transakcji synchronicznej, procedura haka otrzymuje kod haka MSGF_DDEMGR. Głównym niebezpieczeństwem korzystania z synchronicznej pętli modalnej transakcji jest to, że modalna pętla utworzona przez okno dialogowe może zakłócać jego działanie. Transakcje asynchroniczne powinny być zawsze używane, gdy biblioteka DDEML jest używana przez bibliotekę DLL.

Kontrola transakcji

Aplikacja może zawiesić transakcje do funkcji wywołania zwrotnego DDE albo tych transakcji skojarzonych z określoną obsługą konwersacji lub wszystkimi transakcjami niezależnie od uchwytu konwersacji. Ta funkcja jest przydatna, gdy aplikacja odbiera transakcję, która wymaga długotrwałego przetwarzania. W takim przypadku aplikacja może zwrócić CBR_BLOCK kod powrotu, aby zawiesić przyszłe transakcje skojarzone z obsługą konwersacji transakcji, aby aplikacja mogła przetwarzać inne konwersacje.

Po zakończeniu przetwarzania aplikacja wywołuje funkcję DdeEnableCallback w celu wznowienia transakcji skojarzonych z zawieszoną konwersacją. Wywołanie DdeEnableCallback powoduje ponowne wysłanie transakcji DDEML, która spowodowała zawieszenie konwersacji przez aplikację. W związku z tym aplikacja powinna przechowywać wynik transakcji w taki sposób, aby mógł uzyskać i zwrócić wynik bez ponownego przetwarzania transakcji.

Aplikacja może zawiesić wszystkie transakcje skojarzone z określonym dojściem do konwersacji, określając dojście i flagę EC_DISABLE w wywołaniu do DdeEnableCallback. Określając dojście NULL, aplikacja może zawiesić wszystkie transakcje dla wszystkich konwersacji.

Po zawieszeniu konwersacji DDEML zapisuje transakcje dla konwersacji w kolejce transakcji. Po ponownym włączeniu konwersacji aplikacja DDEML usuwa zapisane transakcje z kolejki i przekazuje każdą transakcję do odpowiedniej funkcji wywołania zwrotnego. Pojemność kolejki transakcji jest duża, ale aplikacja powinna jak najszybciej przywrócić zawieszoną konwersację, aby uniknąć utraty transakcji.

Aplikacja może wznowić zwykłe przetwarzanie transakcji, określając flagę EC_ENABLEALL w DdeEnableCallback. W celu bardziej kontrolowanego wznowienia przetwarzania transakcji aplikacja może określić flagę EC_ENABLEONE. Ta flaga usuwa jedną transakcję z kolejki transakcji i przekazuje ją do odpowiedniej funkcji wywołania zwrotnego; po przetworzeniu tej transakcji wszystkie konwersacje zostaną ponownie wyłączone.

Jeśli flaga EC_ENABLEONE i uchwyt konwersacji są określone w wywołaniu DdeEnableCallback, tylko ta konwersacja jest blokowana po przetworzeniu transakcji. Jeśli określono obsługę konwersacji null, wszystkie konwersacje są blokowane po przetworzeniu transakcji w dowolnej konwersacji.

Klasy transakcji

DDEML ma cztery klasy transakcji. Każda klasa jest identyfikowana przez stałą rozpoczynającą się od prefiksu XCLASS_. Klasy są definiowane w pliku nagłówka DDEML. Wartość klasy jest połączona z wartością typu transakcji i jest przekazywana do funkcji wywołania zwrotnego DDE aplikacji odbierającego.

Klasa transakcji określa wartość zwracaną przez funkcję wywołania zwrotnego, która ma zostać zwrócona, jeśli przetwarza transakcję. Następujące wartości zwracane i typy transakcji są skojarzone z każdą z czterech klas transakcji.

Klasa Wartość zwracana Transakcja
XCLASS_BOOL true lub FALSE XTYP_ADVSTART
XTYP_CONNECT
XCLASS_DATA Dojście danych, kod powrotny CBR_BLOCK lub NULL XTYP_ADVREQ
XTYP_REQUEST
XTYP_WILDCONNECT
XCLASS_FLAGS Flaga transakcji: DDE_FACK, DDE_FBUSY lub DDE_FNOTPROCESSED XTYP_ADVDATA
XTYP_EXECUTE
XTYP_POKE
XCLASS_NOTIFICATION Żaden XTYP_ADVSTOP
XTYP_CONNECT_CONFIRM
XTYP_DISCONNECT
XTYP_ERROR
XTYP_REGISTER
XTYP_UNREGISTER
XTYP_XACT_COMPLETE

Typy transakcji

Każdy typ transakcji DDE ma odbiornik i skojarzone działanie, które powoduje wygenerowanie każdego typu przez DDEML.

Typ transakcji Odbiornik Przyczyna
XTYP_ADVDATA Klient Serwer odpowiedział na transakcję XTYP_ADVREQ, zwracając uchwyt danych.
XTYP_ADVREQ Serwer Serwer o nazwie funkcja DdePostAdvise wskazująca, że wartość elementu danych w pętli doradcy uległa zmianie.
XTYP_ADVSTART Serwer Klient określił typ transakcji XTYP_ADVSTART w wywołaniu funkcji DdeClientTransaction.
XTYP_ADVSTOP Serwer Klient określił typ transakcji XTYP_ADVSTOP w wywołaniu DdeClientTransaction.
XTYP_CONNECT Serwer Klient o nazwie funkcji DdeConnect i określił nazwę usługi i nazwę tematu obsługiwaną przez serwer.
XTYP_CONNECT_CONFIRM Serwer Serwer zwrócił true w odpowiedzi na transakcję XTYP_CONNECT lub XTYP_WILDCONNECT.
XTYP_DISCONNECT Klient/serwer Partner w konwersacji o nazwie funkcji DdeDisconnect, co powoduje, że obaj partnerzy otrzymają tę transakcję.
XTYP_ERROR Klient/serwer Wystąpił błąd krytyczny. DDEML może nie mieć wystarczających zasobów do kontynuowania.
XTYP_EXECUTE Serwer Klient określił typ transakcji XTYP_EXECUTE w wywołaniu DdeClientTransaction.
XTYP_MONITOR Aplikacja do monitorowania DDE W systemie wystąpiło zdarzenie DDE. Aby uzyskać więcej informacji na temat aplikacji do monitorowania DDE, zobacz Monitoring Applications.
XTYP_POKE Serwer Klient określił typ transakcji XTYP_POKE w wywołaniu DdeClientTransaction.
XTYP_REGISTER Klient/serwer Aplikacja serwera użyła funkcji DdeNameService w celu zarejestrowania nazwy usługi.
XTYP_REQUEST Serwer Klient określił typ transakcji XTYP_REQUEST w wywołaniu DdeClientTransaction.
XTYP_UNREGISTER Klient/serwer Aplikacja serwera używana DdeNameService do wyrejestrowania nazwy usługi.
XTYP_WILDCONNECT Serwer Klient o nazwie DdeConnect lub funkcji DdeConnectList, określając null dla nazwy usługi, nazwy tematu lub obu tych elementów.
XTYP_XACT_COMPLETE Klient Transakcja asynchroniczna, wysłana, gdy klient określił flagę TIMEOUT_ASYNC w wywołaniu DdeClientTransaction, zakończył.