Blocking calls in AsyncCallback?

H

Hoov

I am writing (in C#) a transaction processing middle-tier server that
needs to handle 2000+ concurrent connections. The server receives a
connection and routes the connection to an appropriate upstream
server. After routing is done, this mid-tier server simply acts as a
pass-though between the client and the upstream server. The
communication protocol is well defined and non-variable.

The pseudo code for each connection looks like this:

Read routing data from client.
Open connection to upstream server.
Send primer data to server.
Read message length from client.
Read message payload from client.
Send length to upstream server.
Send payload to upstream server.
Read response length from upstream server.
Read response message from upstream server.
Terminate upstream server connection.
Send response length to client.
Send response payload to client.
Terminate client connection.

I have already figured out that Asynchronous sockets should be used
for this implementation as apposed to a multi-threaded, blocking
socket implementation.

I started writing this and came up with a question: After the initial
Stream.BeginRead, why shouldn't I use blocking calls once my initial
AsyncCallback has been entered? Are there any advantages to doing
"chained" Asynchronous calls?

Ex: Chained callbacks

Socket.BeginRead(state.buffer, 0, kRoutingDataSize,
ReadRoutingCallback);

Void ReadRoutingCallback(IAsyncResult ar)
{
int iBytesRead = ar.state.stream.EndRead(ar);

//Processing code
int iPayloadLen = GetLenFromBuffer(ar.AsyncState);
ar.state.stream.BeginRead(state.buffer, 0, iPayloadLen,
ReadPayloadCallback, state);
}

Etc, etc.


Ex: Blocking in initial callback

Socket.BeginRead(state.buffer, 0, kRoutingDataSize,
ReadRoutingCallback);

Void ReadRoutingCallback(IAsyncResult ar)
{
int iBytesRead = ar.state.stream.EndRead(ar);

//Processing code
int iPayloadLen = GetLenFromBuffer(ar.AsyncState);
ar.state.stream.Read(state.buffer, 0, iPayloadLen,
ReadPayloadCallback, state);

//Continue complete message processing using blocking calls
}

Etc, etc.

Processing time is very important in this implementation. Why not use
blocking calls in the initial callback?
Are Async socket calls always faster?

Any opinions/suggestions are very much appreciated.

Thanks,
John
 
H

Hoov

[...]
Processing time is very important in this implementation. Why not use
blocking calls in the initial callback?
Are Async socket calls always faster?

The main reason not to use blocking calls in your async callback is that  
the async callback happens on a special thread, dedicated to processing  
completions for i/o completion ports.  There are many of these threads,  
but they are also used widely and should be left to do what they are  
intended for: processing i/o completions.

Your async callback should do as little handling of the data as is  
absolutely necessary, optionally post a new operation (i.e. call the  
"Begin..." method again), and then return.  Sometimes you can put business  
logic in that callback (or at least in something the callback calls), but  
often it's more appropriate for the callback method to simply move the  
data to somewhere that represents a higher level of abstraction in your  
design, and let a different thread deal with it later.

(Note, by the way, that "move" may not involve any actual  
copying...sometimes it's sufficient to just put a reference to the buffer  
that's been completed into a queue somewhere, depending on how the  
higher-level abstraction is designed).

In either case, you should take care to not spend very much time in the  
callback method.

Pete

Thank you so much. This is exactly what I wanted to know.

As a side note. I wrote the proof-of-concept application as multi-
threaded. Just to show managment that we could do this.
It is simple and small... I am now about half-way through the async
implementation... anything but simple!

Thanks again,
John
 
P

Peter Morris

Your async callback should do as little handling of the data as is
absolutely necessary, optionally post a new operation (i.e. call the
"Begin..." method again), and then return.

How would the server pass the result onto the client without calling
End...(), and doesn't End....() block the current thread?


Pete
 
H

Hoov

How would the server pass the result onto the client without calling
End...(), and doesn't End....() block the current thread?

Pete

Technically your are correct. But a simple experiment shows me that
the callback method is not called until there is actually data
available or the timeout limit has been reached. So, there is little
to no blocking that occurs on the call to End...().

John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top