My EXE server is a serial communications oriented server using the Async
Professional components from Turbo Power.
I also wrote a Client Component, which you drop on your client application's
form and just use it. The client sends a command or query (a string) to the
server ( MyClient.Execute('COMMAND') ), which the server then queues up until
the serial port is free, and it returns a handle for the client to hold onto,
then it does the protocol stuff, and then stores the resulting information
(packets coming back in the serial port) and then sends an event back to the
client object when the data has been received, along with a handle so that the
client can verify that this is the data it has been waiting for. The event
contains a string array, and in this way we pass the results back to the client.
If the client wishes, the data can be "polled" repeatedly and the handle helps
the client identify who owns the resultant data.
This allows several different client applications to make requests from this
slow serial device simultaneously. The requests are serialized in a queue of my
own creation. Because serial communications are slow (device connection speeds
on the various modems we use vary from 1200 bps to 33.6kbps) it's important that
the Server.Execute('command') returns a handle (an integer) and that an event is
fired when the command has been executed.
I initially thought of a design using named pipes or sockets, and not using COM
at all, but I actually have a complex COM interface now with 20 events and 30 or
so different commands, not just the Execute command, and the Results event. So
I'd like to stay with COM now, but I'm having problems.
My serial communications components (Async Professional, from Turbo Power
Software) give me results through standard Delphi VCL event notifications (a
callback, basically). From inside these Callbacks, I'm calling Binh Ly's
implementation of an IConnectionPointContainer which notifies all connected
parties of things like a connection being dropped, or some other error
condition, or of new data being available to read, etc. The
IConnectionPointContainer implementation iterates through the list of connected
parties and tries to call them with IDispatch.Invoke(...), which fails with the
following error:
"An outgoing call cannot be made since the application is dispatching an
input-synchronous call."
The HResult from IDispatch.Invoke is $8001010D and this means that it was an
error from the RPC facility, and the error code
is defined as RPC_E_CANTCALLOUT_ININPUTSYNCCALL
Is this likely caused because AsyncPro is calling my event code from inside it's
own thread context? If so could this error be caused when that thread context
not initialized for COM to use?
Should I set up some kind of marshalling?
My own quick hack was to manually serialize using a PostMessage() type hack. The
problem is I have 20 events to handle, and I have a feeling that posting 20
different things into a message queue, and then manually decoding the incoming
messages from the queue, and then calling COM I would be going around the
procedure that COM would intend me to use.
Any ideas what I should do?
Warren
It took me a day before I figured out that this was the reason :-(
I to created a windows, and posted messages from the AsyncPro event.
I hope someone here can show a better way
regards John
If that's the case, whenever you receive an event from Async Pro, and then
make a COM call out from your object, COM will normally ensure that you
don't make a synchronous call that can possibly block because while you're
making the call, COM will allow and process pending messages in your
object's apartment (that may include messages coming in from Async Pro). If
your object makes a blocking call that may take a while, that will probably
disrupt your serial data processing because your object might process
incoming data while it's still making a call to the client.
The solution as you've found is to post a message to yourself and make the
outgoing call later. You don't have to post to a single main thread. You can
also create additional secondary threads and use the PostThreadMessage call
and handle them as if you were handling normal windows messages.
If you want further info in input-synchronized calls in COM, check out
Inside OLE 2 by Kraig Brockshmidt.
have fun
--
Binh Ly
Visit my COM Notes at http://www.castle.net/~bly/com
Warren Postma <em...@geocities.com> wrote in message
news:7s8fth$17...@forums.borland.com...