嵌套线程与c#

时间:2011-05-02 21:40:51

标签: c# multithreading bluetooth chat

嗨,我对一般的线程非常新。 我在c#中开发类似蓝牙聊天的东西。 主要形式有2种可能性 1.更新BT设备列表并连接到设备(工作正常) 2.听取连接到自己的BT芯片的设备。

用于测试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();
            }
        }
    }

因为监听总是正确的,所以创建并显示了新的表单(new 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
            {
            }

        }
    }

第二种形式的流是来自简单的带有1位数的.txt streamReader的流。 第二个线程陷入无限循环(或似乎是这样),应用程序崩溃。 我既不知道问题在哪里,也不知道如何解决问题。

// 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 个答案:

答案 0 :(得分:1)

我很确定该条款隐藏了这个问题:

    catch
    {
    }

删除它,因为它捕获所有异常并且不执行任何操作。删除后再次以调试模式运行,您将看到实际错误。看看here

答案 1 :(得分:0)

您的receiveData方法非常奇怪。

所以它在非UI线程上调用。假设它读取的字节不是-1。

需要调用,因此它会自行调用。

现在它读取一个字节并得到-1(你说文件只有1位数)。

现在它在循环中永远旋转。

此外,如果您在UI线程上调用该方法并且它读取一个字节,则它必须在输出之前读取另一个字节。

如果你正在查看尚未关闭的网络流,那么这也可能挂在第二次调用stream.ReadByte上。在关闭流之前,您的代码无法知道已到达终点。这与文件不同。

您还没有创建一种逃避循环的方法。此方法中的任何内容都不会将listening设置为false。而且由于它在UI线程上旋转,你无法按下取消按钮或其他任何东西。

我认为你想要做的是:

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

答案 2 :(得分:0)

所以Stream.ReadByte()说:

  

从流中读取一个字节并将流中的位置前进一个字节,如果在流的末尾则返回-1。

一旦网络流关闭,它就会保持这种状态。所以小溪说:我已经关闭了。但是你的代码继续循环,得到-1,并循环并得到-1并循环。你需要这样做:

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并抛出值,然后将 next 字节发送到屏幕。

上面的Jim Mischel已经说过了,但你好像错过了他的答案。 : - )

接受

无论如何还有一个早期的问题......什么是'stream'被初始化为?假设您使用32feet.NET中的BluetoothListener(使用相同的模式和FCL的TcpListener和IrDAListener),则需要接受新连接。你在某个地方做那个吗?我希望checkForConnection能够做到:

while (!appQuitting) {
  // This blocks waiting for a incoming connection...
  var conn = listener.AcceptBluetoothClient();
  var strm = conn.GetStream();
  ThreadPool.QueueUserWorkItem(DataRead_Runner, strm);
}

答案 3 :(得分:0)

表单很可能无法正确创建,因为您正在使用来自后台线程的消息来填充它,该消息始终在紧密的无限循环中执行。

为什么不尝试使用“阻塞”流,以阻止线程执行,直到通过蓝牙接收到实际数据