вложенные темы с C # - PullRequest
       14

вложенные темы с C #

1 голос
/ 03 мая 2011

Привет, я очень новичок в темах вообще. Я разрабатываю что-то вроде Bluetooth-чата в c #. На основной форме есть 2 возможности 1. Обновление списка устройств BT и подключение к устройству (Работает нормально) 2. Прослушайте устройства, подключенные к собственному чипу BT.

для проверки работоспособности БТ отключен.

для # 2 я создал тему после загрузки формы.

    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();
            }
        }
    }

потому что прослушивание всегда верно, создается и отображается новая форма (новая sendReceiveForm).

новая форма содержит другой поток, который выполняется после загрузки новой формы и имеет цикл, который проверяет поток, есть ли полученная информация.

    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
            {
            }

        }
    }

Поток во второй форме - это поток из простого .txt streamReader с 1 цифрой. второй поток застрял в бесконечном цикле (или, кажется, так), и приложение вылетает. У меня нет ни идеи, где проблема, ни как я могу ее исправить.

// EDIT

Обновлен метод до:

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

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

но без разницы

// EDIT2

Дело в том, что он работает нормально до запуска 2 потока. если я прокомментирую начало потока 2, форма будет создана и, кажется, будет работать нормально.

Ответы [ 4 ]

1 голос
/ 03 мая 2011

Я почти уверен, что проблема скрыта этим пунктом:

    catch
    {
    }

удалите его, потому что он перехватывает все исключения и ничего с ним не делает.После удаления запустите снова в режиме отладки, и вы увидите фактическую ошибку.Взгляните здесь .

0 голосов
/ 04 мая 2011

Форма, вероятно, не создана должным образом, поскольку вы заполняете ее сообщениями из фонового потока, который всегда выполняется в тесном бесконечном цикле.

Почему бы вам не попробовать использовать «блокирующий» поток, чтобы он блокировал выполнение потока до тех пор, пока не будут получены реальные данные по Bluetooth

0 голосов
/ 04 мая 2011

Так Stream.ReadByte () говорит:

Считывает байт из потока и продвигает позицию в потоке на один байт или возвращает -1, если в конце потока.

Как только сетевой поток закрывается, он остается таким же. Итак, поток говорит: я закрыт. Но ваш код продолжает цикл, и получить -1, и цикл, и получить -1, и цикл. Вы должны сделать, например ::100100

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 ...
  }
}

Обратите внимание, что это устраняет вторую проблему в вашем примере кода ... Он выполняет ReadByte и выбрасывает значение, а затем отправляет следующий байт на экран.

Джим Мишель выше уже говорил это, но вы, кажется, пропустили его ответ. : -)

Accept

В любом случае, есть более ранняя проблема ... Как инициализируется поток? Предполагая, что вы используете BluetoothListener из 32feet.NET (который использует тот же шаблон и TcpListener и IrDAListener FCL), вам необходимо принять новое соединение. Вы делаете это где-нибудь? Я ожидаю, что checkForConnection сделает:

while (!appQuitting) {
  // This blocks waiting for a incoming connection...
  var conn = listener.AcceptBluetoothClient();
  var strm = conn.GetStream();
  ThreadPool.QueueUserWorkItem(DataRead_Runner, strm);
}
0 голосов
/ 03 мая 2011

Ваш receiveData метод довольно странный.

Так что он вызывается в потоке без пользовательского интерфейса. Допустим, он читает байт, который не равен -1.

Требуется Invoke, поэтому он сам перезванивает.

Теперь он читает байт и получает -1 (вы сказали, что файл содержит только 1 цифру).

И теперь он вращается вечно в цикле.

Кроме того, если вы вызываете метод в потоке пользовательского интерфейса и он читает байт, ему придется прочитать еще один байт, прежде чем он выведет.

Это может также зависать при втором вызове stream.ReadByte, если вы смотрите на сетевой поток, который еще не закрыт. Ваш код не может знать, что конец достигнут, пока поток не будет закрыт. Это отличается от файла.

Вы не создали способ избежать цикла. Ничто в этом методе не устанавливает listening в false. И поскольку он вращается в потоке пользовательского интерфейса, вы не можете нажать кнопку отмены или что-либо еще.

Я думаю, что вы хотите сделать это:

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());
        }
    }
}
...