I've got an interesting issue with a program I'm writing. I think I know kinda what is wrong, but I'm not sure about it, and I don't know how to fix it. I have the following code

.
.
.
                string strCmd = "command";
                OnDataSend(strCmd);
                //wait for a response
                while (!(m_szdata.Contains("OK\r\n")) && !(m_szdata.Contains("error")) &&
                    !(m_szdata.Contains("ERROR"))) ;
                if (m_szdata.Contains("OK\r\n"))
                {
                    btnLogin.Enabled = true;
                    OnUpdateServerStats();
                }
                else
                    MessageBox.Show("Error selecting server number.\r\n Please select another server.",
                        "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        private void OnUpdateServerStats()
        {
            string strCmd = "serverstats\r\n";
            string strData;
            string[] strParts, strSeps = { "\r\n", "=" };
                        
            OnDataSend(strCmd);
            //Wait for a response
            while (!(m_szdata.Contains("OK\r\n")) && !(m_szdata.Contains("error")) &&
                !(m_szdata.Contains("ERROR"))) ;

            strData = m_szdata;
            m_szdata = "";
            strParts = strData.Split(strSeps, StringSplitOptions.RemoveEmptyEntries);
 
            string c = "";
            foreach (string z in strParts)
                c += z + Environment.NewLine;
            MessageBox.Show(c, string.Format("{0} elements", strParts.Length));

        }

Here's where I run in to problems. The program runs fine until it calls OnUpdataServerStats(). When it gets here it freezes and I know why (damn infinite loop). If I comment out the while statement it doesn't freeze, but my output shows 0 elements. (However I have all data received output to an edit box and all the data shows up there). Now if I take and comment out OnUpdataServerStats() and put it say in a button like the following

private void btnTest_Click(object sender, EventArgs e)
        {
            OnUpdateServerStats();
        }

I get the proper number of elements and I can even leave the while statement in there and it doesn't lock up. I suspect it has something to do with the way the data is being received (which is Asynchronously), but I'm not sure how to fix that issue. Any suggestions?

I'm going to make a small guess here, feel free to correct me.

while (!(m_szdata.Contains("OK\r\n")) && !(m_szdata.Contains("error")) &&
                !(m_szdata.Contains("ERROR"))) ;

            strData = m_szdata;
            m_szdata = "";

Am I right to say that this loop runs for as long as m_szdata does NOT contain OK, error or ERROR. Since you then change m_szdata to "", it still hasn't got ok, error or ERROR in it, so the while will go on again...and again...and again.

You should make your m_szdata null I think, and then break your while if szdata.isnull.

Feedback is welcome.

That won't work. Remember if the while statement is removed it works, but not correctly. If the OnUpdateServerStats() is called with a button it works fine(unless you've already tried to call that function from before. It only works like intended if you don't call that function from the previous one). When using the original code, it's like it's not receiving ANY data until AFTER it's done with the OnUpdateServerStats().

Hi there atrusmre, I take it you or not getting any compilation error/warnings? How about trying this (just a quick idea I am not sure if it will work)

while (!(m_szdata.Contains("OK\r\n")) && !(m_szdata.Contains("error")) &&
                    !(m_szdata.Contains("ERROR"))) ;
                    btnLogin.Enabled = true;
                    OnUpdateServerStats();

You see I am not entirely sure what that IF is checking for that is different from what the WHILE is checking for

aaah I think I see now, the while loop is checking to see whether m_szdata.contains DOES NOT contain "OK\r\n" therefore and if that IF statement is inside that WHILE the IF will never be true because WHILE is checking if m_szdata is NOT "Ok\r\n" is that correct? Is the IF inside the WHILE?Not sure why you have the ; at the end of the WHILE

I don't know. I would say that you have a logical flaw or that I don't know enough of c# :p

while (!(m_szdata.Contains("OK\r\n")) && !(m_szdata.Contains("error")) &&
                    !(m_szdata.Contains("ERROR"))) ;
                if (m_szdata.Contains("OK\r\n"))

Your while does end with ; which seems curious. It doesn't really do anything that way.
Secondly, even if that IF - statement was nested in the while, it would never be used since your while triggers when your string does not containt ok, error etc..., but your IF relies on the presence of 'OK' in your string.

But it can be that I am just misunderstanding your total program. I just don't see the logic at this moment :p.

EDIT: Don't mind too much, I think I'm starting to see something here. I showed it to some of my mates and one subtly showed me your ondatasend above the while. I overlooked this one. I'll try to relook at the code with that in mind after I get home :p.

As far as I can see, Jens and I are thinking along the same lines. I.e that the problem lies with your While and If loops.

Yes, but I showed it to some friends and they noted 'OnDataSend'.
He uses the while to 'pause' the program as long as he is fetching his data from ondatasend. After he got his OK, error or ERROR, he goes to the next line.
I just wasn't familiar with that method of working.

So it just keeps on running after you try to call ondatasend twice. And m_szdata is off course assigned in ondatasend.
I'll take more looks when I finally get home, but at least I grasped the logic already.

Yes, but I showed it to some friends and they noted 'OnDataSend'.
He uses the while to 'pause' the program as long as he is fetching his data from ondatasend. After he got his OK, error or ERROR, he goes to the next line.
I just wasn't familiar with that method of working.

That is correct, the while statement is being used as a 'pause'. As I noted before, I can take out the while statement, and it shows 0 elements, it should show the server's stats. But it doesn't, until after the UpdateServerStats function is finished. Not sure why. It's like calling the OnDataSend twice causes issues.

I did mention this was a network application didn't I? If not, sorry, but it is.

True

If ondatasend is in a different class, you could try to call a new instance of this class. This way you would make sure that none of the data from your first ondatasend() get carried over.

I also have another question about m_szdata.
Lets see, I assume this is a global or public variable (since you use it in datasend and updateserverstats).

OnDataSend(strCmd);
                //wait for a response
                while (!(m_szdata.Contains("OK\r\n")) && !(m_szdata.Contains("error")) &&
                    !(m_szdata.Contains("ERROR"))) ;
                if (m_szdata.Contains("OK\r\n"))
                {
                    btnLogin.Enabled = true;
                    OnUpdateServerStats();
                }

If this works, m_szdata contains an OK. right? The button gets enabled and you can start calling on updateserverstats.

Now, does m_szdata keep this ok, or does he overwrite it in ondatasend?

It would be handy to be able to take a looksie at ondatasend, actually :p

True

If ondatasend is in a different class, you could try to call a new instance of this class. This way you would make sure that none of the data from your first ondatasend() get carried over.

I also have another question about m_szdata.
Lets see, I assume this is a global or public variable (since you use it in datasend and updateserverstats).

OnDataSend(strCmd);
                //wait for a response
                while (!(m_szdata.Contains("OK\r\n")) && !(m_szdata.Contains("error")) &&
                    !(m_szdata.Contains("ERROR"))) ;
                if (m_szdata.Contains("OK\r\n"))
                {
                    btnLogin.Enabled = true;
                    OnUpdateServerStats();
                }

If this works, m_szdata contains an OK. right? The button gets enabled and you can start calling on updateserverstats.

Now, does m_szdata keep this ok, or does he overwrite it in ondatasend?

It would be handy to be able to take a looksie at ondatasend, actually :p

Correct m_szdata is a global variable and it gets reset to "" during OnDataSend.

And I'll do you one better, I've included the receive functions as well

private void btnSelectServer_Click(object sender, EventArgs e)
        {
            string strResponse, strSvrNum;
            string[] strParts, strSeps = { "\r\n" };
            frmSelectServer frmSelSvr = new frmSelectServer();

            //the Server List Command
            string strCmd = "sl\r\n";

            //Send the command
            OnDataSend(strCmd);

            //wait for a respose
            while (!(m_szdata.Contains("OK\r\n"))) ;//potental infinite loop

            strResponse = m_szdata;
            strParts = strResponse.Split(strSeps, StringSplitOptions.RemoveEmptyEntries);

            //Populate the combo box
            foreach (string strTemp in strParts)
                if (!(strTemp.Contains("OK")))
                    frmSelSvr.cmbServer.Items.Add(strTemp);

            //Select Server number
            if (frmSelSvr.ShowDialog() == DialogResult.OK)
            {
                strSvrNum = frmSelSvr.cmbServer.SelectedItem.ToString();

                //The Select Server Command
                strCmd = "sel " + strSvrNum + "\r\n";

                //Send the command
                OnDataSend(strCmd);
                //wait for a response
                while (!(m_szdata.Contains("OK\r\n")) && !(m_szdata.Contains("error")) &&
                    !(m_szdata.Contains("ERROR"))) ;
                if (m_szdata.Contains("OK\r\n"))
                {
                    btnLogin.Enabled = true;
                    btnListChannels.Enabled = true;
                    btnListUsers.Enabled = true;
                    OnUpdateServerStats();
                }
                else
                    MessageBox.Show("Error selecting server number.\r\n Please select another server.",
                        "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
 private void OnUpdateServerStats()
        {
            string strCmd = "si\r\n";
            string strData;
            string[] strParts, strSeps = { "\r\n", "=" };
                        
            OnDataSend(strCmd);
            txtResults.Text += strCmd;
            //Wait for a response
            while (!(m_szdata.Contains("OK\r\n")) && !(m_szdata.Contains("error")) &&
                !(m_szdata.Contains("ERROR"))) ;
          
            strData = m_szdata;
            m_szdata = "";
            strParts = strData.Split(strSeps, StringSplitOptions.RemoveEmptyEntries);
 
            string c = "";
            foreach (string z in strParts)
                c += z + Environment.NewLine;
            MessageBox.Show(c, string.Format("{0} elements", strParts.Length));
        }
public void WaitForData()
        {
            if (pfnCallBack == null)
            {
                pfnCallBack = new AsyncCallback(OnDataReceived);
            }
            //listen for data
            m_asynResult = m_host.BeginReceive(m_DataBuffer, 0, m_DataBuffer.Length, SocketFlags.None, pfnCallBack, null);
        }
public void OnDataReceived(IAsyncResult asyn)
        {
            if (m_host.Connected == true)
            {
                //end receive
                int iRx = 0;
                iRx = m_host.EndReceive(asyn);
                char[] chars = new char[iRx + 1];
                System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
                int charLen = d.GetChars(m_DataBuffer, 0, iRx, chars, 0);
                m_szdata = new System.String(chars);

                this.SetText(txtResults.Text + m_szdata);
                WaitForData();
            }
        }
public void OnDataSend(string strTemp)
        {
            //clear the receive buffer
            m_szdata = "";
            m_host.Send(Encoding.ASCII.GetBytes(strTemp));
        }
This article has been dead for over six months. Start a new discussion instead.