/// <summary> /// This should be called only after a lock on sendRequests has been acquired. /// It pings back and forth with the BytesSent callback to send out all the strings in /// the queue. This method gets the string at the front of the queue and attempts /// to send it. BytesSent takes care of making sure all of the bytes are actually sent /// before calling this method again to send the next string. /// </summary> private void ProcessSendQueue() { while (sendRequests.Count > 0) { sendBytes = encoding.GetBytes(sendRequests.First().Text); try { socket.BeginSend(sendBytes, sendCount = 0, sendBytes.Length, SocketFlags.None, BytesSent, null); break; } catch (Exception e) { SendRequest req = sendRequests.Dequeue(); ThreadPool.QueueUserWorkItem(x => req.Callback(e, req.Payload)); } } }
/// <summary> /// This method is the callback used when bytes are being sent. It makes sure that all of /// the bytes have been sent, then calls the appropriate callback and calls ProcessSendQueue. /// </summary> private void BytesSent(IAsyncResult ar) { try { // Compute how many bytes have been sent so far sendCount += socket.EndSend(ar); } catch (Exception e) { SendRequest req = sendRequests.Dequeue(); ThreadPool.QueueUserWorkItem(x => req.Callback(e, req.Payload)); ProcessSendQueue(); return; } // If all the bytes were sent, remove the request from the queue, notify the // callback, and process the next entry in the send queue. if (sendCount == sendBytes.Length) { lock (sendRequests) { SendRequest req = sendRequests.Dequeue(); ThreadPool.QueueUserWorkItem(x => req.Callback(null, req.Payload)); ProcessSendQueue(); } } // If all the bytes weren't sent, send the rest. else { try { socket.BeginSend(sendBytes, sendCount, sendBytes.Length - sendCount, SocketFlags.None, BytesSent, null); } catch (Exception e) { SendRequest req = sendRequests.Dequeue(); ThreadPool.QueueUserWorkItem(x => req.Callback(e, req.Payload)); ProcessSendQueue(); } } }