In MSDN example of using asynchronous sockets, the receiving data in socket is done by repeatedly calling asynchronous BeginReceive from the callback handler which is called by BeginReceive:
private static void ReceiveCallback( IAsyncResult ar ) {
//...Skipped...
if (bytesRead > 0) {
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer,0,bytesRead));
// Get the rest of the data.
client.BeginReceive(state.buffer,0,StateObject.BufferSize,0,
new AsyncCallback(ReceiveCallback), state);
} else {
// ...Skipped...
}
http://msdn.microsoft.com/en-us/library/bbx2eya8(v=vs.110).aspx
Is there a necessity to make again an asynchronous call from a handler which is already executing in a separate thread? Can one simply use Receive in a loop in this handler? Something like:
while (bytesRead) {
bytesRead = client.Receive(state.buffer, 0, client.Available,
SocketFlags.None);
// Etc...
}
The major goal of the APM pattern was to avoid blocking the calling thread while waiting for the result of asynchronous operation, and thus boost the scalability of the server applications.
If in your
AsyncCallback
you continue callingReceive
in the loop synchronously, you'll still be blocking the IOCP thread on which the initialBeginReceive
has completed. This may be OK for a client-side UI app, where you might not care aboutThreadPool
starvation, but this is certainly not a good idea for a server-side app, where the blocked thread could otherwise be serving other incoming client requests.Note that with C# 5.0 / .NET 4.5 and on, APM is considered legacy. You can use
async/await
andnew Task-based Asynchronous Pattern (TAP)
pattern, which greatly simplifies the asynchronous code development, e.g.:If for some reason you don't want to use
NetworkStream.ReadAsync
, you can wrap APM-style socket APIs as TAP withTask.FromAsync
: