ALL,
Have the following problem. First, here is my code:
class InternetConnector { private static ManualResetEvent receiveDone = new ManualResetEvent( false ); public static ManualResetEvent processingDone = new ManualResetEvent( false ); public static ConcurrentQueue<string> messages = new ConcurrentQueue<string>(); public static bool Connected; public bool ReceiveMessage(Action<Socket> successHandler, Action<Exception> errorHandler) { bool receive = false; ClientStateObject obj = new ClientStateObject(); obj.server = client; var connectionData = new ConnectionData { ErrorHandler = errorHandler, SuccessHandler = successHandler, Socket = client, clientObj = obj }; if (Connected) { client.BeginReceive(connectionData.clientObj.buffer, 0, ClientStateObject.bufSize, 0, new AsyncCallback(ReceiveCallback), connectionData); receive = true; receiveDone.WaitOne(); } return receive; } private static void ReceiveCallback(IAsyncResult ar) { ConnectionData connectionData = new ConnectionData(); bool complete = false; try { connectionData = (ConnectionData)ar.AsyncState; Socket client = connectionData.Socket; int num = client.EndReceive(ar); { connectionData.clientObj.stringBuffer.Append(Encoding.ASCII.GetString(connectionData.clientObj.buffer, 0, num)); string response = connectionData.clientObj.stringBuffer.ToString(); if (response.EndsWith("&")) complete = true; string[] msgs = response.Split('&'); int j = 0; if (!complete) j++; for (int i = 0; i < msgs.Count() - j; i++) { string sts = msgs[i]; if (i == 0 && receivingMessage != String.Empty) { sts = receivingMessage + sts; messages.Enqueue(sts + "&" ); receivingMessage = String.Empty; } else messages.Enqueue(sts + "&"); } if (!complete) receivingMessage += msgs[msgs.Count() - 1]; else receivingMessage = String.Empty; receiveDone.Set(); if (connectionData.SuccessHandler != null) { connectionData.SuccessHandler(client); processingDone.WaitOne(); client.BeginReceive(connectionData.clientObj.buffer, 0, ClientStateObject.bufSize, 0, new AsyncCallback(ReceiveCallback), connectionData); } } } catch (Exception e) { if (connectionData.ErrorHandler != null) connectionData.ErrorHandler(e); } } } And here is the success handler:
public partial class Form1 : Form { private void AsyncSuccessHandler(Socket socket) { if (InvokeRequired) { BeginInvoke(new Action( () => AsyncSuccessHandler( socket ) )); return; } if (InternetConnector.messages.Count() == 0) { status.Text = "Signals Receiver: Connected"; status.ForeColor = Color.Green; startStop.Text = "Stop"; isRunning = true; create.Enabled = true; SetGUIColorsAndValues(); client.SendMessageToConnector("First Signal Pass4&"); client.ReceiveMessage(AsyncSuccessHandler, AsyncErrorHandler); } else { SetGUIColorsAndValues(); GUIChangeOnConnection(); InternetConnector.processingDone.Set(); } } private void GUIChangeOnConnection() { for( int i = 0; i < InternetConnector.messages.Count; i++ ) { string message; InternetConnector.messages.TryDequeu( out message ); // process message } } } Problem: I need to continuosly read the data from the server and display them in the GUI. I also need the GUI to be responsive to i.e. button clicks. I also need to start n read iteration when n-1 read iteration has been finished processing and the concurrentqueue object in my code is empty.
However going thru the code in debugger I can see that BeginReceive() call in the reading callback does not wait till the end of success handler and the queue is not empty.
What am I missing? Is there a better way to achieve this?
I am also aware of SignalR library but at this pont I don't want to use any 3rd party library.
Any help in this matter appreciated.
Thank you.
[EDIT]
Do I understand Amit's reply correctly:
class InternetConnector { private static ManualResetEvent processingDone = new ManualResetEvent( false ); private static void ReceiveCallback(IAsyncResult ar) { ConnectionData connectionData = new ConnectionData(); bool complete = false; try { connectionData = (ConnectionData)ar.AsyncState; Socket client = connectionData.Socket; int num = client.EndReceive(ar); { connectionData.clientObj.stringBuffer.Append(Encoding.ASCII.GetString(connectionData.clientObj.buffer, 0, num)); string response = connectionData.clientObj.stringBuffer.ToString(); if (response.EndsWith("&")) complete = true; string[] msgs = response.Split('&'); int j = 0; if (!complete) j++; for (int i = 0; i < msgs.Count() - j; i++) { string sts = msgs[i]; if (i == 0 && receivingMessage != String.Empty) { sts = receivingMessage + sts; messages.Enqueue(sts + "&" ); receivingMessage = String.Empty; } else messages.Enqueue(sts + "&"); } if (!complete) receivingMessage += msgs[msgs.Count() - 1]; else receivingMessage = String.Empty; receiveDone.Set(); if (connectionData.SuccessHandler != null) { processingDone.WaitOne(); connectionData.SuccessHandler(client); processingDone.Set(); client.BeginReceive(connectionData.clientObj.buffer, 0, ClientStateObject.bufSize, 0, new AsyncCallback(ReceiveCallback), connectionData); } } } catch (Exception e) { if (connectionData.ErrorHandler != null) connectionData.ErrorHandler(e); } } } ?
[/EDIT] [EDIT 2] Please see updated code. When I set a breakpoint at the very end of the GUIChangeOnConnection() - line with the "}" - I see that the queue does have some items. I will try to change ManualResetEvent, in the meantime. [/EDIT 2]