1

Hi im very new to threads in general. Iam developing something like a Bluetooth Chat in c#. On the main form are 2 possibilities 1. updating the list of BT devices and connect to a device (Works fine) 2. Listen for devices connecting to the own BT chip.

for testing the BT functionality is disabled.

for #2 i created a thread after loading the form.

    private void MainForm_Load(object sender, EventArgs e)
    {           
        incomingConnectionThread = new Thread(checkForConnection);
        incomingConnectionThread.Start();
    }

    public void checkForConnection()
    {
        while (listening) //boolean which is always true
        {
            if (cargui == null)
            {
                cargui = new sendReceiveForm(null);
                cargui.ShowDialog();
            }
        }
    }

because listening is always true a new form (new sendReceiveForm) is created and shown.

the new form contains another thread which is executed after the loading of the new form and has a loop which checks a stream if there is information received.

    private void CarGui_Load(object sender, EventArgs e)
    {
        thread = new Thread(receiveData);
        thread.Start();
    }

    private void receiveData()
    {
        while (listening)
        {
            try
            {
                if (stream.ReadByte() != -1)
                {
                    if (rtfReceiveWindow.InvokeRequired)
                    {
                        rtfReceiveWindow.Invoke(new rtfDelegate(receiveData));
                    }

                    else
                    {
                        rtfReceiveWindow.Text += stream.ReadByte().ToString();
                    }
                }                 
            }
            catch
            {
            }

        }
    }

The stream in the second form is the stream from a simple .txt streamReader with 1 digit. the second thread is stuck in an infinite loop (or seems so) and the app crashes. i have neither an idea where the problem is nor how i can fix it.

//EDIT

Updated the method to:

private void receiveData()
    {
        while (listening)
        {               
            if (stream.ReadByte() != -1)
            {
                if (rtfReceiveWindow.InvokeRequired)
                {
                    rtfReceiveWindow.Invoke(new rtfDelegate(receiveData));
                }

                else
                {
                    rtfReceiveWindow.Text += stream.ReadByte().ToString();
                }
            }                  
        }
    }

but no difference

//EDIT2

The thing is it works fine until starting the 2 thread. if i comment the start of the 2 thread the form is created and seems to work fine.

Alex
  • 11
  • 3

4 Answers4

1

I am pretty sure that problem is hidden by this clause:

    catch
    {
    }

remove it, because it catches all exceptions and does nothing with it. After you remove it run again in debug mode and you will see the actual error. Take a look here.

Community
  • 1
  • 1
Andrey
  • 59,039
  • 12
  • 119
  • 163
  • thx 4 your reply. i deleted try/catch but sadly i does not make any difference. an interesting fact might be that the ne form is displayed in an "unfinished" status. the form elements looks like "placeholders". – Alex May 02 '11 at 21:49
  • 2
    @Alex pls update the question, it is impossible to read code in comments – Andrey May 02 '11 at 21:50
  • @Alex okay, you say that application crashes in **debug** mode and Visual Studio doesn't show you any exception? – Andrey May 02 '11 at 21:54
  • its not actually "crashing" but an infinite loop. the program always jumps from the while to the if ( in the thread ) and back again until i stop the execution – Alex May 02 '11 at 21:56
  • @Alex but it is what you application does! It runs in infinite loop. why should it not "jump from the while to the if"? If you want it not to freeze you can add `Thread.Sleep` somewhere in between. – Andrey May 02 '11 at 22:02
  • @Andrey ye i know that but the question is: Why is the form not created properly? – Alex May 02 '11 at 22:06
  • @Alex try to add `Thread.Sleep(1000)` in the loop and tell me whether form is created ok. – Andrey May 03 '11 at 09:14
0

Your receiveData method is pretty strange.

So it's called on a non-UI thread. Let's say it reads a byte that's not -1.

Invoke is required, so it calls itself back.

Now it reads a byte and gets a -1 (you said the file has only 1 digit).

And now it spins forever in the loop.

Also, if you call the method on the UI thread and it reads a byte, it'll have to read another byte before it outputs.

This could also be hanging on that second call to stream.ReadByte, if you're looking at a network stream that hasn't been closed. Your code can't know that the end has been reached until the stream is closed. That's different from a file.

You haven't created a way to escape the loop. Nothing in this method sets listening to false. And since it's spinning on the UI thread, there's no way for you to press a cancel button or anything.

I think what you want to do is this:

private void updateReceived(string s)
{
    if (rtfReceiveWindow.InvokeRequired)
    {
        rtfReceiveWindow.Invoke(new Action(() => updateReceived(s); }));
    }
    rtfReceiveWindow.Text += s;
}

private void receiveData()
{
    while (listening)
    {
        int recv = stream.ReadByte();
        if (recv != -1)
        {
            updateReceived(recv.ToString());
        }
    }
}
Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
0

So Stream.ReadByte() says:

Reads a byte from the stream and advances the position within the stream by one byte, or returns -1 if at the end of the stream.

Once a network stream is shut it stays that way. So the stream is saying: I'm closed. But your code continues to loop, and get -1, and loop and get -1 and loop. You need to do e.g.:

void DataReader_Runner(object state)
{
  Stream strm = (Stream)state;
  while (true) {
    int bi = strm.ReadByte(); // This blocks waiting for data...
    if (bi == -1)
      break;
    byte b = (byte)bi; // Now we know that it is not the special -1 int value
    ... use the new byte ...
  }
}

Note that fixes a second problem in your code sample... It does ReadByte and throws the value away, and then send the next byte to the screen.

Jim Mischel above has said this already but you seem to have missed his answer. :-)

Accept

Anyway there's a earlier problem... What is 'stream' being initialised as? Assuming you are using BluetoothListener from 32feet.NET (which uses the same pattern and the FCL's TcpListener and IrDAListener), you need to Accept a new connection. Do you do that somewhere? I'd expect checkForConnection to do:

while (!appQuitting) {
  // This blocks waiting for a incoming connection...
  var conn = listener.AcceptBluetoothClient();
  var strm = conn.GetStream();
  ThreadPool.QueueUserWorkItem(DataRead_Runner, strm);
}
alanjmcf
  • 3,430
  • 1
  • 17
  • 14
0

The form is likely not created properly because you are flooding it with messages from your background thread which is always executing in a tight infinite loop.

Why dont you try to use a "blocking" stream so that it blocks the thread from executing until there is actual data received over bluetooth

dmg
  • 608
  • 8
  • 15