Holy cow, I wrote a book!
"Isn't DDE all asynchronous anyway?"
asks commenter KaiArnold.
It's mostly asynchronous, but not entirely.
You can read about
how DDE works in MSDN,
but since it seems people are reluctant to read the formal
documentation, I'll repeat here the points relevant to the discussion.
The DDE process begins with a search for a service provider.
This is done by broadcasting the WM_DDE_INITIATE
message and collecting the responses.
Each server that wishes to respond to the request sends
back a WM_DDE_ACK message.
The DDE client then chooses which of the servers it wishes
to continue the conversation with (possible more than one).
The remainder of the DDE conversation is carried out with
posted messages, the details of which are not important here.
As you can see, everything in DDE is asynchronous with the
exception of the WM_DDE_INITIATE.
Why is WM_DDE_INITIATE synchronous?
Remember that DDE was developed back in the 16-bit days,
when it was safe to broadcast messages.
The initiate message and its WM_DDE_ACK replies
are synchronous to ensure that the client doesn't have to
wait indefinitely to build a list of servers.
If it were asynchronous, then the client would post the
WM_DDE_INITIATE and then wait
"a while" to see if anybody responded.
But how does it know when it should give up waiting and just
go with whatever it has?
What happens if a response comes in after the client already
proceeded based on the assumption that that server was unavailable?
What if a response comes in five minutes later, when the client
had started a second DDE discovery query?
Would that response have been to the first or the second discovery
it is important for the client to know whether there are any
servers out there at all,
because the way the shell
interprets DDE-based file associations
is first to attempt a WM_DDE_INITIATE
with the application and topic specified in the registration.
If no server is found, then it launches the server manually
and then tries to connect to the server via DDE a second time.
(The second time should work, since the responsible server
was explicitly launched!)