The information in this article applies to:
SUMMARYDDEML servers are applications that provide data to client applications. For some servers, this data gathering may be a lengthy process, as when gathering data from sources such as serial ports or a network. DDEML allows a server application to process data asynchronously in these situations by returning CBR_BLOCK from the DDE callback function. MORE INFORMATION
In DDEML-based applications, while transactions can be either
synchronous or asynchronous, only DDEML client applications may choose
to establish either type of transaction when requesting data from a
server application. DDEML server applications do not distinguish
between synchronous and asynchronous transactions.
Method 1Given that DDEML callbacks are not re-entrant, and that DDEML expects a data handle as a return value from the XTYP_REQUEST transaction (and transactions of XCLASS_DATA class), the server application can block the callback momentarily. It can do this by returning a CBR_BLOCK value after posting itself a user-defined message. This way, the server application can gather data in the background while DDEML queues up any further transactions. The server can start gathering data when its window procedure gets the user defined message that was posted by its DDE callback function. When a server application returns CBR_BLOCK for a request transaction, DDEML disables the server's callback function. It also queues transactions that are sent by DDEML after its callback has been disabled. This feature gives the server an opportunity to gather data while allowing other applications to run in the system. As soon as data becomes available, then the server application can call DdeEnableCallBack() to re-enable the server callback function. Once the callback is re-enabled, DDEML will resend the same request transaction to the server's callback and this time, because data is ready, the server application can return the appropriate data handle to the client. Transactions that were queued up because of an earlier block are sent to the server's callback function in the order they were received by DDEML. The pseudo code to implement method 1 might resemble the following: BOOL gbGatheringData = TRUE; // Defined GLOBAlly. HDDEDATA ghData = NULL; HDDEDATA CALLBACK DdeServerCallBack(...)
switch(txnType) { case XTYP_REQUEST:
if(bGatheringData) { PostMessage(hSrvWnd, WM_GATHERDATA, .....) ; return CBR_BLOCK; } else // Data is ready, send back handle. return ghData; default: return DDE_FNOTPROCESSED; } } LRESULT CALLBACK SrvWndProc(...) { switch (wMessage) { case WM_GATHERDATA: while (bGatheringData) { // Gather data here while yielding to others // at the same time! if(!PeekMessage(..)) bGatheringData = GoGetDataFromSource (&ghData); else { TranslateMessage() ; DispatchMessage (); } } DdeEnableCallback (idInst, ghConv, EC_ENABLEALL); break ; default: return DefWndProc(); } } Method 2Advise transactions in DDEML (or DDE) are just a continuous request link. Changing the transaction from a REQUEST to a "one time only" ADVISE loop on the client side allows the server to gather data asynchronously. The client application can start an ADVISE transaction from its side and when the server receives a XTYP_ADVSTART transaction, return TRUE so that an ADVISE link is established. Once the link is established, the server can start gathering data, and as soon as it becomes available, notify the client of its availability. This can be done by calling DdePostAdvise(). The server can use PeekMessage() to gather data if the data gathering process is a lengthy one, so that other applications on the system will get a chance to run. Once the client receives the data from the server in its callback (in its XTYP_ADVDATA transaction), it can disconnect the the ADVISE link from the server by specifying an XTYP_ADVSTOP transaction. Additional query words: 3.10 3.50 4.00
Keywords : |
Last Reviewed: September 21, 1999 © 2000 Microsoft Corporation. All rights reserved. Terms of Use. |