트랜잭션 관리(데이터 교환)

서버와 대화를 설정한 후 클라이언트는 트랜잭션을 보내 서버에서 데이터 및 서비스를 가져올 수 있습니다.

다음 topics 클라이언트가 서버와 상호 작용하는 데 사용할 수 있는 트랜잭션 유형에 대해 설명합니다.

트랜잭션 요청

클라이언트 애플리케이션은 XTYP_REQUEST 트랜잭션을 사용하여 서버 애플리케이션에서 데이터 항목을 요청할 수 있습니다. 클라이언트는 DdeClientTransaction 함수를 호출하여 XTYP_REQUEST 트랜잭션 형식으로 지정하고 애플리케이션에 필요한 데이터 항목을 지정합니다.

DDEML(동적 데이터 교환 관리 라이브러리)은 클라이언트가 요청한 토픽 이름, 항목 이름 및 데이터 형식을 지정하여 XTYP_REQUEST 트랜잭션을 서버에 전달합니다. 서버가 요청된 항목, 항목 및 형식을 지원하는 경우 서버는 항목의 현재 값을 식별하는 데이터 핸들을 반환해야 합니다. DDEML은 이 핸들을 DdeClientTransaction의 반환 값으로 클라이언트에 전달합니다. 요청된 항목, 항목 또는 형식을 지원하지 않는 경우 서버는 NULL 을 반환해야 합니다.

DdeClientTransactionlpdwResult 매개 변수를 사용하여 트랜잭션 상태 플래그를 클라이언트에 반환합니다. 서버가 XTYP_REQUEST 트랜잭션을 처리하지 않으면 DdeClientTransactionNULL을 반환하고 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을 사용하여 서버 애플리케이션의 항목에 대한 하나 이상의 링크를 설정할 수 있습니다. 이러한 링크가 설정되면 서버는 연결된 항목에 대한 정기적인 업데이트를 클라이언트에 보냅니다(일반적으로 서버 애플리케이션과 연결된 항목의 값이 변경될 때마다). 연결은 클라이언트가 종료될 때까지 그대로 유지되는 두 애플리케이션 간에 조언 루프를 설정합니다.

"핫"과 "따뜻한"의 두 가지 종류의 조언 루프가 있습니다. 핫 조언 루프에서 서버는 변경된 값을 식별하는 데이터 핸들을 즉시 보냅니다. 웜 조언 루프에서 서버는 항목 값이 변경되었음을 클라이언트에 알리지만 클라이언트가 요청할 때까지 데이터 핸들을 보내지 않습니다.

클라이언트는 DdeClientTransaction 호출에서 XTYP_ADVSTART 트랜잭션 형식을 지정하여 서버에서 핫 어드바이스 루프를 요청할 수 있습니다. 웜 조언 루프를 요청하려면 클라이언트가 XTYPF_NODATA 플래그를 XTYP_ADVSTART 트랜잭션 유형 과 결합해야 합니다. 두 경우 모두 DDEML은 XTYP_ADVSTART 트랜잭션을 서버의 DDE(동적 데이터 교환) 콜백 함수에 전달합니다. 서버의 DDE 콜백 함수는 XTYP_ADVSTART 트랜잭션과 함께 제공되는 매개 변수(요청된 형식, 토픽 이름 및 항목 이름 포함)를 검사한 다음 TRUE 를 반환하여 advise 루프 또는 FALSE 가 이를 거부할 수 있도록 해야 합니다.

advise 루프가 설정되면 서버 애플리케이션은 요청된 항목 이름과 연결된 항목의 값이 변경될 때마다 DdePostAdvise 함수를 호출해야 합니다. 이 호출로 인해 XTYP_ADVREQ 트랜잭션이 서버의 DDE 콜백 함수로 전송됩니다. 서버의 DDE 콜백 함수는 데이터 항목의 새 값을 식별하는 데이터 핸들을 반환해야 합니다. 그런 다음 DDEML은 클라이언트의 DDE 콜백 함수에 XTYP_ADVDATA 트랜잭션을 전송하여 지정된 항목이 변경되었음을 클라이언트에 알립니다.

클라이언트가 핫 어드바이스 루프를 요청한 경우 DDEML은 XTYP_ADVDATA 트랜잭션 중에 변경된 항목에 대한 데이터 핸들을 클라이언트에 전달합니다. 그렇지 않으면 클라이언트는 XTYP_REQUEST 트랜잭션을 보내 데이터 핸들을 가져올 수 있습니다.

서버가 클라이언트가 새 데이터를 처리할 수 있는 것보다 더 빠르게 업데이트를 보낼 수 있습니다. 업데이트 속도는 데이터에 대해 긴 처리 작업을 수행해야 하는 클라이언트의 문제일 수 있습니다. 이 경우 클라이언트는 조언 루프를 요청할 때 XTYPF_ACKREQ 플래그를 지정해야 합니다. 이 플래그를 사용하면 서버가 다음 데이터 항목을 보내기 전에 클라이언트가 데이터 항목을 수신하고 처리했음을 인정할 때까지 기다립니다. XTYPF_ACKREQ 플래그로 설정된 조언 루프는 빠른 서버에서 더 강력하지만 업데이트를 놓칠 수 있습니다. XTYPF_ACKREQ 플래그 없이 설정된 Advise 루프는 클라이언트가 서버를 따라가는 한 업데이트를 놓치지 않도록 보장됩니다.

클라이언트는 DdeClientTransaction 호출에서 XTYP_ADVSTOP 트랜잭션 유형을 지정하여 조언 루프를 종료할 수 있습니다.

서버에서 advise 루프를 지원하지 않는 경우 DdeInitialize 함수에서 CBF_FAIL_ADVISES 필터 플래그를 지정해야 합니다. 이 플래그를 사용하면 DDEML이 XTYP_ADVSTARTXTYP_ADVSTOP 트랜잭션을 서버에 보내지 않습니다.

트랜잭션 실행

클라이언트는 XTYP_EXECUTE 트랜잭션을 사용하여 서버가 명령 또는 일련의 명령을 실행하도록 할 수 있습니다.

서버 명령을 실행하기 위해 클라이언트는 먼저 서버가 실행할 명령 문자열이 포함된 버퍼를 만든 다음 , DdeClientTransaction을 호출할 때 버퍼를 식별하는 데이터 핸들 또는 버퍼에 대한 포인터를 전달합니다. 기타 필수 매개 변수로는 대화 핸들, 항목 이름 문자열 핸들, 형식 사양 및 XTYP_EXECUTE 트랜잭션 유형이 있습니다. 실행 데이터를 전달하는 데이터 핸들을 만드는 애플리케이션은 DdeCreateDataHandle 함수의 hszItem 매개 변수에 NULL을 지정하고 uFmt 매개 변수에는 0을 지정해야 합니다.

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이 클라이언트에 전달하는 매개 변수 중 하나는 트랜잭션 식별자입니다. 클라이언트는 이 트랜잭션 식별자를 DdeClientTransaction에서 반환된 식별자와 비교하여 서버에서 처리를 완료한 비동기 트랜잭션을 식별합니다.

클라이언트는 비동기 트랜잭션을 처리하는 데 도움이 되면서 DdeSetUserHandle 함수를 사용할 수 있습니다. 이 함수를 사용하면 클라이언트가 애플리케이션 정의 값을 대화 핸들 및 트랜잭션 식별자와 연결할 수 있습니다. 클라이언트는 XTYP_XACT_COMPLETE 트랜잭션 중에 DdeQueryConvInfo 함수를 사용하여 애플리케이션 정의 값을 가져올 수 있습니다. 이 함수로 인해 애플리케이션은 활성 트랜잭션 식별자 목록을 유지할 필요가 없습니다.

클라이언트가 동기 트랜잭션을 사용하여 데이터 요청을 성공적으로 완료하면 DDEML은 클라이언트가 수신된 데이터 사용을 완료한 시기를 알 수 없습니다. 클라이언트 애플리케이션은 DdeFreeDataHandle 함수에 수신된 데이터 핸들을 전달하여 DDEML에 핸들이 더 이상 사용되지 않음을 알려야 합니다. 동기 트랜잭션에서 반환된 데이터 핸들은 클라이언트가 효과적으로 소유합니다.

서버가 적시에 비동기 트랜잭션을 처리하지 않는 경우 클라이언트는 DdeAbandonTransaction 함수를 호출하여 트랜잭션을 중단할 수 있습니다. DDEML은 트랜잭션과 연결된 모든 리소스를 해제하고 서버에서 처리를 완료하면 트랜잭션 결과를 삭제합니다. 동기 트랜잭션 중 시간 제한은 트랜잭션을 효과적으로 취소합니다.

비동기 트랜잭션 메서드는 계산 수행과 같은 상당한 양의 처리를 동시에 수행하면서 대량의 DDE 트랜잭션을 보내야 하는 애플리케이션에 대해 제공됩니다. 비동기 메서드는 중단 없이 다른 작업을 완료할 수 있도록 일시적으로 DDE 트랜잭션 처리를 중지해야 하는 애플리케이션에서도 유용합니다. 대부분의 다른 상황에서 애플리케이션은 동기 메서드를 사용해야 합니다.

동기 트랜잭션은 유지 관리가 더 간단하고 비동기 트랜잭션보다 빠릅니다. 그러나 한 번에 하나의 동기 트랜잭션만 수행할 수 있지만 많은 비동기 트랜잭션을 동시에 수행할 수 있습니다. 동기 트랜잭션을 사용하면 느린 서버로 인해 클라이언트가 응답을 기다리는 동안 유휴 상태를 유지할 수 있습니다. 또한 동기 트랜잭션으로 인해 클라이언트는 애플리케이션의 자체 메시지 루프에서 메시지 필터링을 무시할 수 있는 모달 루프를 입력합니다.

클라이언트가 메시지를 필터링하는 후크 프로시저를 설치한 경우(즉, SetWindowsHookEx 함수에 대한 호출에서 WH_MSGFILTER 후크 유형을 지정함) 동기 트랜잭션으로 인해 시스템이 후크 프로시저를 우회하지 않습니다. 클라이언트가 동기 트랜잭션이 종료될 때까지 기다리는 동안 입력 이벤트가 발생하면 후크 프로시저는 MSGF_DDEMGR 후크 코드를 받습니다. 동기 트랜잭션 모달 루프를 사용하는 기본 위험은 대화 상자에서 만든 모달 루프가 해당 작업을 방해할 수 있다는 것입니다. DLL에서 DDEML을 사용할 때는 항상 비동기 트랜잭션을 사용해야 합니다.

트랜잭션 제어

애플리케이션은 특정 대화 핸들과 연결된 트랜잭션 또는 대화 핸들에 관계없이 모든 트랜잭션 중 하나의 DDE 콜백 함수에 대한 트랜잭션을 일시 중단할 수 있습니다. 이 기능은 애플리케이션이 긴 처리가 필요한 트랜잭션을 수신할 때 유용합니다. 이러한 경우 애플리케이션은 CBR_BLOCK 반환 코드를 반환하여 트랜잭션의 대화 핸들과 연결된 향후 트랜잭션을 일시 중단하여 애플리케이션이 다른 대화를 자유롭게 처리할 수 있도록 할 수 있습니다.

처리가 완료되면 애플리케이션은 DdeEnableCallback 함수를 호출하여 일시 중단된 대화와 관련된 트랜잭션을 다시 시작합니다. DdeEnableCallback을 호출하면 DDEML이 트랜잭션을 다시 보내어 애플리케이션이 대화를 일시 중단합니다. 따라서 애플리케이션은 트랜잭션을 다시 처리하지 않고 결과를 가져오고 반환할 수 있는 방식으로 트랜잭션의 결과를 저장해야 합니다.

애플리케이션은 DdeEnableCallback 호출에서 핸들 및 EC_DISABLE 플래그를 지정하여 특정 대화 핸들과 연결된 모든 트랜잭션을 일시 중단할 수 있습니다. NULL 핸들을 지정하면 애플리케이션이 모든 대화에 대한 모든 트랜잭션을 일시 중단할 수 있습니다.

대화가 일시 중단되면 DDEML은 트랜잭션 큐에서 대화에 대한 트랜잭션을 저장합니다. 애플리케이션이 대화를 다시 활성화하면 DDEML은 큐에서 저장된 트랜잭션을 제거하고 각 트랜잭션을 적절한 콜백 함수에 전달합니다. 트랜잭션 큐의 용량은 크지만 애플리케이션은 트랜잭션 손실을 방지하기 위해 가능한 한 빨리 일시 중단된 대화를 다시 활성화해야 합니다.

애플리케이션은 DdeEnableCallback에서 EC_ENABLEALL 플래그를 지정하여 일반적인 트랜잭션 처리를 다시 시작할 수 있습니다. 트랜잭션 처리의 보다 제어된 다시 시작의 경우 애플리케이션은 EC_ENABLEONE 플래그를 지정할 수 있습니다. 이 플래그는 트랜잭션 큐에서 하나의 트랜잭션을 제거하고 적절한 콜백 함수에 전달합니다. 해당 트랜잭션이 처리된 후 모든 대화가 다시 비활성화됩니다.

EC_ENABLEONE 플래그와 대화 핸들이 DdeEnableCallback 호출에 지정된 경우 트랜잭션이 처리된 후에만 해당 대화가 차단됩니다. 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 함수라는 서버는 advise 루프의 데이터 항목 값이 변경되었음을 나타냅니다.
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 서버 서비스 이름, 토픽 이름 또는 둘 다에 대해 NULL을 지정하는 DdeConnect 또는 DdeConnectList 함수라는 클라이언트입니다.
XTYP_XACT_COMPLETE 클라이언트 클라이언트가 DdeClientTransaction 호출에서 TIMEOUT_ASYNC 플래그를 지정했을 때 전송되는 비동기 트랜잭션이 종료되었습니다.