Board index » delphi » Client/Server blocking problem with DCOM

Client/Server blocking problem with DCOM

I'm working on a relatively simple DCOM (actually currently I'm just testing
on my machine) and I'm having a problem wrt to blocking.  I'm very new to
COM, so please excuse and stupid questions.

In any event, I need to be able to call methods in the server that might be
<very> lengthy to complete (on the order or minutes) in the worst case, or
might complete as quickly as a couple hundred milliseconds.

So, question one:  what is the best way (any way for that matter) to
implement a non-blocking call to a COM server.  Currently if call a method
that takes 100ms to complete I get a Catastrophic Failure exception and the
client isn't very happy.  I'm assuming I can use a thread on the server end
(which is easy enough) to offload the work so that the method can complete
immediately, and then use an event from the server back to the client for
notification of completion.  If I do that, how do I communicate with the COM
class on the server end?  I assume the class is not thread-safe, and being
that it's not a 'window' I can't PostMessage back.

Question two (actually this is probably a sub-question to one):  Is there
any way to create an asynchronous method call.  IE, call the method in the
server, the method returns a response (Processing?) immediately. After this
the server can keep processing the call and then trigger an event back to
the client.

Imagine that I want to create a remote compressor/decompressor, and you're
not to far off of what I want to accomplish with the design.

Thanks for any suggestions,
Michael Trainor
K-R Automation
mtrai...@krauto.com

 

Re:Client/Server blocking problem with DCOM


Details I forgot to mention.

First, I'm using D4 with the update (I know the COM stuff changed in D4 and
I decided to wait instead of using D3 as I hoped that it would be
easier<g>).

Second, my server is ciMultiInstance, which I believe is necessary to keep
the individual client connections from interfering with each other,
performance-wise.

Third, my test on the server side to use up time is just a timed while loop
(rather than getting all the heavy code in yet).  Is there something I need
to do to notify the client that I'm still working (something like
application.processmessages, I hope <not>).

Thanks again
Michael Trainor
K-R Automation
mtrai...@krauto.com

Quote
Michael Trainor <mtrai...@krauto.com> wrote in message

6seu8j$7v...@forums.borland.com...
Quote
>I'm working on a relatively simple DCOM (actually currently I'm just
testing
>on my machine) and I'm having a problem wrt to blocking.  I'm very new to
>COM, so please excuse and stupid questions.

>In any event, I need to be able to call methods in the server that might be
><very> lengthy to complete (on the order or minutes) in the worst case, or
>might complete as quickly as a couple hundred milliseconds.

>So, question one:  what is the best way (any way for that matter) to
>implement a non-blocking call to a COM server.  Currently if call a method
>that takes 100ms to complete I get a Catastrophic Failure exception and the
>client isn't very happy.  I'm assuming I can use a thread on the server end
>(which is easy enough) to offload the work so that the method can complete
>immediately, and then use an event from the server back to the client for
>notification of completion.  If I do that, how do I communicate with the
COM
>class on the server end?  I assume the class is not thread-safe, and being
>that it's not a 'window' I can't PostMessage back.

>Question two (actually this is probably a sub-question to one):  Is there
>any way to create an asynchronous method call.  IE, call the method in the
>server, the method returns a response (Processing?) immediately. After this
>the server can keep processing the call and then trigger an event back to
>the client.

>Imagine that I want to create a remote compressor/decompressor, and you're
>not to far off of what I want to accomplish with the design.

>Thanks for any suggestions,
>Michael Trainor
>K-R Automation
>mtrai...@krauto.com

Re:Client/Server blocking problem with DCOM


Hi, Michael,

I'm dealing with a similar issue. This is one of the things that isn't
obvious about COM, at least it wasn't immediately to me. The COM method is
executing in the server, and so obviously it can't return until the server
has finished. This is a remote procedure call. End of story. Uncoupling two
processes is no simple task. There is talk of truly async COM in the COM+
timeframe. There are some specialty cases, like ADO, right now, but overall
you have to work around the problems in your code. The core issues are
queueing and notifications. Unless I'm mistaken, general purpose COM
currently has no intrinsic mechanisms for those.

There are several suggestions one can make. You could just use sockets, e.g.
UDP packets in both directions. You could use windows messaging instead, as
a form of "for free" queuing if you are running on one machine. You can use
memory maped files and pipes in that context too, but you may need to create
your own queueing. Pipes can work across a network. You can get into MS
MessageQueue, which is probably the hard core and correct approach. You can
use a one-two COM approach where your first method starts the process, and
the server notifies with a callback or an Event. This latter approach might
fit the bill. If you are multi-instance when you attach the connection point
for the event, you always pass a cookie to the server, and that's how it
knows who is who, so it takes care of itself. In D4 the event support on the
client side is weak. If you get a headache, use Binh Ly's EventSinkImp
utility that makes a client side component out of an event created on the
server side (which is easy to create in D4). See his web site

http://www.castle.net/~bly/Programming/

 You will end up having to create your own state machine to keep track I
think.

Any COM gurus have any other observations?

Fernand

Quote
Michael Trainor wrote in message <6seun8$7v...@forums.borland.com>...
>Michael Trainor <mtrai...@krauto.com> wrote in message
>6seu8j$7v...@forums.borland.com...
>>I'm working on a relatively simple DCOM (actually currently I'm just
>testing
>>on my machine) and I'm having a problem wrt to blocking.  I'm very new to
>>COM, so please excuse and stupid questions.

>>In any event, I need to be able to call methods in the server that might
be
>><very> lengthy to complete (on the order or minutes) in the worst case, or
>>might complete as quickly as a couple hundred milliseconds.

>>So, question one:  what is the best way (any way for that matter) to
>>implement a non-blocking call to a COM server.  Currently if call a method
>>that takes 100ms to complete I get a Catastrophic Failure exception and
the
>>client isn't very happy.  I'm assuming I can use a thread on the server
end
>>(which is easy enough) to offload the work so that the method can complete
>>immediately, and then use an event from the server back to the client for
>>notification of completion.  If I do that, how do I communicate with the
>COM
>>class on the server end?  I assume the class is not thread-safe, and being
>>that it's not a 'window' I can't PostMessage back.

>>Question two (actually this is probably a sub-question to one):  Is there
>>any way to create an asynchronous method call.  IE, call the method in the
>>server, the method returns a response (Processing?) immediately. After
this
>>the server can keep processing the call and then trigger an event back to
>>the client.

>>Imagine that I want to create a remote compressor/decompressor, and you're
>>not to far off of what I want to accomplish with the design.

>>Thanks for any suggestions,
>>Michael Trainor
>>K-R Automation
>>mtrai...@krauto.com

Re:Client/Server blocking problem with DCOM


There are two general solutions to your problem:

A. The client is a COM server by itself and exposes a simple interface that
works as a notification sink (or call it callback interface). When the
client calls the server, it passes an object to itself to the server,
alongside any other parameters reqired. When the server has done the job, it
uses this "handle" to notify the client. For this purpose, the server has to
keep an internal reference to this (client) object, until the job is done.
The only problem with this method is the possibility, that the client might
terminate while the server is working, so the callback goes into nirwana.
Normally, that should only happen if the client crashes, since the server
side reference keeps the client from terminating.
Anyway, this is the "old" OLE way. Method B is the better solution.

B. The Server implements COM notifications, and the client  implements an
"advise sink". The Delphi 4  includes a demo on how to implement that on the
client side (see .../demos/activeX/word8). I can't explain, how to RAISE COM
events using  Delphi, because I haven't done it yet, but with Visual Basic
it's extremly simple.
This only hint I can give here is the fact, that the notification type and
its parameters must be included in the servers TLB.

In general terms, imagine method B as a kind of "broadcast" where the
servers doesn't need to have a reference to the client. Method A is more
like posting a message to a window, so the client has to give it's window
handle to the server.

Decoupling the server from the client (make the call async) can be done by
timer(s) or using threads. Please note that serialization might still block
a client if more that one client calls a single threaded (single instance)
server.

I hope that helps a bit.

Sigi Stephan

Quote
Michael Trainor wrote in message <6seu8j$7v...@forums.borland.com>...
>I'm working on a relatively simple DCOM (actually currently I'm just
testing
>on my machine) and I'm having a problem wrt to blocking.  I'm very new to
>COM, so please excuse and stupid questions.

>In any event, I need to be able to call methods in the server that might be
><very> lengthy to complete (on the order or minutes) in the worst case, or
>might complete as quickly as a couple hundred milliseconds.

>So, question one:  what is the best way (any way for that matter) to
>implement a non-blocking call to a COM server.  Currently if call a method
>that takes 100ms to complete I get a Catastrophic Failure exception and the
>client isn't very happy.  I'm assuming I can use a thread on the server end
>(which is easy enough) to offload the work so that the method can complete
>immediately, and then use an event from the server back to the client for
>notification of completion.  If I do that, how do I communicate with the
COM
>class on the server end?  I assume the class is not thread-safe, and being
>that it's not a 'window' I can't PostMessage back.

>Question two (actually this is probably a sub-question to one):  Is there
>any way to create an asynchronous method call.  IE, call the method in the
>server, the method returns a response (Processing?) immediately. After this
>the server can keep processing the call and then trigger an event back to
>the client.

>Imagine that I want to create a remote compressor/decompressor, and you're
>not to far off of what I want to accomplish with the design.

>Thanks for any suggestions,
>Michael Trainor
>K-R Automation
>mtrai...@krauto.com

Re:Client/Server blocking problem with DCOM


Hello Fernand,

I guess your statement is a bit pessimistic. There is no need to wait for
COM+ since everything is in place already.

Decoupling the client from the server is most easily done with a timer and
COM events.
For those who own VB5: There is a very complete example (coffee), that
includes the use of STA and MTA threads.
Would be interesting if someone  would translate that to Delphi. That would
help a lot of people to get started. May be i'll try that one day.

Sigi Stephan

Quote
Fernand Raynaud wrote in message <6shsts$cf...@forums.borland.com>...
>Hi, Michael,

>I'm dealing with a similar issue. This is one of the things that isn't
>obvious about COM, at least it wasn't immediately to me. The COM method is
>executing in the server, and so obviously it can't return until the server
>has finished. This is a remote procedure call. End of story. Uncoupling two
>processes is no simple task. There is talk of truly async COM in the COM+
>timeframe. There are some specialty cases, like ADO, right now, but overall
>you have to work around the problems in your code. The core issues are
>queueing and notifications. Unless I'm mistaken, general purpose COM
>currently has no intrinsic mechanisms for those.

>There are several suggestions one can make. You could just use sockets,
e.g.
>UDP packets in both directions. You could use windows messaging instead, as
>a form of "for free" queuing if you are running on one machine. You can use
>memory maped files and pipes in that context too, but you may need to
create
>your own queueing. Pipes can work across a network. You can get into MS
>MessageQueue, which is probably the hard core and correct approach. You can
>use a one-two COM approach where your first method starts the process, and
>the server notifies with a callback or an Event. This latter approach might
>fit the bill. If you are multi-instance when you attach the connection
point
>for the event, you always pass a cookie to the server, and that's how it
>knows who is who, so it takes care of itself. In D4 the event support on
the
>client side is weak. If you get a headache, use Binh Ly's EventSinkImp
>utility that makes a client side component out of an event created on the
>server side (which is easy to create in D4). See his web site

>http://www.castle.net/~bly/Programming/

> You will end up having to create your own state machine to keep track I
>think.

>Any COM gurus have any other observations?

>Fernand

>Michael Trainor wrote in message <6seun8$7v...@forums.borland.com>...
>>Michael Trainor <mtrai...@krauto.com> wrote in message
>>6seu8j$7v...@forums.borland.com...
>>>I'm working on a relatively simple DCOM (actually currently I'm just
>>testing
>>>on my machine) and I'm having a problem wrt to blocking.  I'm very new to
>>>COM, so please excuse and stupid questions.

>>>In any event, I need to be able to call methods in the server that might
>be
>>><very> lengthy to complete (on the order or minutes) in the worst case,
or
>>>might complete as quickly as a couple hundred milliseconds.

>>>So, question one:  what is the best way (any way for that matter) to
>>>implement a non-blocking call to a COM server.  Currently if call a
method
>>>that takes 100ms to complete I get a Catastrophic Failure exception and
>the
>>>client isn't very happy.  I'm assuming I can use a thread on the server
>end
>>>(which is easy enough) to offload the work so that the method can
complete
>>>immediately, and then use an event from the server back to the client for
>>>notification of completion.  If I do that, how do I communicate with the
>>COM
>>>class on the server end?  I assume the class is not thread-safe, and
being
>>>that it's not a 'window' I can't PostMessage back.

>>>Question two (actually this is probably a sub-question to one):  Is there
>>>any way to create an asynchronous method call.  IE, call the method in
the
>>>server, the method returns a response (Processing?) immediately. After
>this
>>>the server can keep processing the call and then trigger an event back to
>>>the client.

>>>Imagine that I want to create a remote compressor/decompressor, and
you're
>>>not to far off of what I want to accomplish with the design.

>>>Thanks for any suggestions,
>>>Michael Trainor
>>>K-R Automation
>>>mtrai...@krauto.com

Other Threads