我用一个专门的线程负责接收来自串口的数据,该线程处于不断的接收状态,串口的数据来源于一个定时器,它每隔6秒发一次数据给串口,当同时启动后接收数据和发送数据都正常,但用户界面不能再操作了,也就是说主线程UI不好响应了,即使响应,马上就处于死机了。 通过调试我可以知道,cpu全部分给接收数据的串口线程了,而且一直在接收,其它线程得不到响应。多线程是交互的呀?? 各位帮忙解决一下吧!谢谢了。我在线等………

解决方案 »

  1.   

    串口接受数据你不要用轮询的方式。用事件来处理。
    串口类都有数据接受事件,即当串口有数据到来时触发这个事件。你用的是;SerialPort类吗?
    SerialPort.DataReceived
      

  2.   

    是啊 
    就是SerialPort 类 
    我是通过线程委托ThreadStart建立的啊
      

  3.   

    线程不能直接操纵ui,需要用invoke,参看
    http://blog.csdn.net/knight94/archive/2006/03/21/631238.aspx
    http://blog.csdn.net/Knight94/archive/2006/05/27/757351.aspx
      

  4.   

    to 通过调试我可以知道,cpu全部分给接收数据的串口线程了,而且一直在接收,其它线程得不到响应。多线程是交互的呀数据线程适当sleep一段时间
      

  5.   

    lifeixie(lifeixie)你好
    我是用定时器用来发送数据给串口,用线程接收数据从串口。
      

  6.   

    线程sleep 也不行的我用过的
    主界面不能操作,
      

  7.   

    private void btnJet_Click(object sender, System.EventArgs e) //喷印
    {
    if ((this.rdbAuto.Checked == true)&&(serialPort1.IsOpen ==true)) // 自动喷印
    {
    if (this.cmbShiftGroup.Text ==string.Empty)
    {
    MessageBox.Show("班组不能为空,请选择班组!","提示");
    return;
    }
    if (this.cmbShiftNo.Text == string.Empty)
    {
    MessageBox.Show("班次不能为空,请选择班次!","提示");
    return;
    }
    keepAlive = true;
    receive  = new Thread(new ThreadStart(ReceiveContent)); //启动喷印线程
    receive.Start();
    this.btnJet.Enabled = false;
    this.timer3.Enabled = true;
    }
    }
      

  8.   

    private void ReceiveContent() // Receive the content from jet machine 接受来自喷印机的信息
    {
    int i = 0;
    //serialPort1.ReadTimeout =3000;
    while(keepAlive==true)
    {
    lock(serialPort1)
    {
    int num;
    byte[] bufferOut = new byte[1];
    if ((num = serialPort1.Read(bufferOut,0,bufferOut.Length))!=0)
    {
    try
    {
    if (bufferOut[0] ==0x32) // require sent jet-content to jet machine  喷印机请求发送喷印内容
    {
    this.txtTubeInfo.Clear();
    JetcolorState = Color.Yellow;
    Invalidate();
    this.Refresh();
    SendContent();
    i++;
    }
    if (bufferOut[0] ==0x33) // sent jet-content successful;  接受喷印机的验证信息 如果正确执行如下
    {
    Successful = true;
    this.txtTubeInfo.Clear();
    this.txtTubeInfo.Text = "完成喷印编号为:" + jetContent.Substring(8,5).Trim()+ " 的钢管" + "\r\n";
    this.stbState.Text = "完成喷印 " + jetContent.Substring(8,5).Trim() + " 号钢管……";
    this.txtTubeMonitor.Text += jetContent.Substring(8,5).Trim() + "\r\n"; // 将当前喷印的钢管号复制于已喷印队列中;
    string sql = "Update Tube_Info set HasPrinted = 1 where DateTime = '" + QueueTable.Table.Rows[0]["DateTime"] + "' and Tube_No = '" + QueueTable.Table.Rows[0]["Tube_No"] + "'";
    SqlCommand cmd = sqlconnect.CreateCommand();
    cmd.CommandText = sql;
    cmd.ExecuteNonQuery(); //更新物理数据库 Tube_Info 对应的钢管 将 Hasprinted 的值设为1 已喷印
    QueueTable.Table.Rows[0].Delete(); //删除喷印队列表中的当前喷印钢管
    // DS3.Tables["Tube_Queue"].Rows[btData.Position].Delete();
    DS3.Tables["Tube_Queue"].AcceptChanges(); // 接受删除
    //DA1.Fill(DS1,"Tube_Info");
    //DA2.Fill(DS2,"Tube_Log");
    //DA3.Fill(DS3,"Tube_Queue");
    JetcolorState = Color.Yellow; //喷印监测灯变正在喷印状态
    this.dgdQueue.SelectionBackColor = Color.Green;
    Invalidate();
    // Thread.Sleep(1000);
    /* if(QueueTable.Table.Rows.Count == 0) // 如果喷印队列中没有钢管则停止喷印,停止接受线程 timer3在此模拟喷印机
    {
    MessageBox.Show("喷印完毕","提示");
    this.timer3.Enabled = false;
    // this.timer5.Enabled  = false;
    this.btnJet.Enabled = true;
    Thread.CurrentThread.Abort();
    this.Refresh();
    } */
    }
    if (bufferOut[0] == 0x25) // sent jet-content fail;如果喷印验证错误则提示喷印出错,要求用户重新开始喷印
    {
    Successful = false;
    JetcolorState = Color.Red;
    Invalidate();
    this.timer3.Enabled = false;
    Thread.CurrentThread.Abort();
    this.btnJet.Enabled = true;
    MessageBox.Show("喷印内容不正确或喷印机出错!","提示");
    this.btnJet.Enabled = true;
    this.Refresh();
    }
    //Thread.Sleep(4700); //每次喷印线程休眠一段时间以等待喷印机发送信息,该过程要细心调试才能做到互动恰当
    //serialPort1.DiscardInBuffer(); // 其中和串口阻塞时间计算机性能有关
    }
    catch (Exception ex)
    {
    MessageBox.Show("Exception : " + ex.Message,"提示");
    return;
    }
    }
    }
    }
    }
      

  9.   

    你的意思是说当串口有数据时再接收??
    如这样的话那就不是不用定义单独的线程了啊??
    ----------
    SerialPort.DataReceived事件采用辅助线程的方式实现对串口数据的读取。
    lz参看这个,应该对你有帮助
    http://blog.csdn.net/showlie/archive/2006/08/10/1046251.aspx
      

  10.   

    先把你的代码贴出来看看。SerialPort类中已有定义的数据接受事件了,为什么还要自己写一个线程呢?
      

  11.   

    实在不行我发你一个串口 接收的 程序吧。 测试过没问题!不过是API的!
      

  12.   

    谢谢各位了先
    我现在改用事件触发的接收串口数据
    我用的是SerialPort 是 .net2003 不是2005
    但是事件不能触发,不知道为什么??
    在家里自己机器上是可以触发的
    但来公司就不行了
    大家说是因为机器的原因吗??还是其他的啊??
    谢谢了
      

  13.   

    家里是Xp 公司是 2000 但我用公司的XP 也是不行的
    不知道是为什么
      

  14.   

    谢谢各位了先
    我现在改用事件触发的接收串口数据
    我用的是SerialPort 是 .net2003 不是2005
    但是事件不能触发,不知道为什么??
    在家里自己机器上是可以触发的
    但来公司就不行了
    大家说是因为机器的原因吗??还是其他的啊??
    谢谢了
      

  15.   

    大家说说看这是为什么啊??
    帮帮忙把
    我现在改用事件触发的接收串口数据
    我用的是SerialPort 是 .net2003 不是2005
    但是事件不能触发,不知道为什么??
    在家里自己机器上是可以触发的
    但来公司就不行了
    大家说是因为机器的原因吗??还是其他的啊??
    谢谢了
      

  16.   

    SerialPort 接收不能触发原因一般都是串口配置不对引起的:)
    你尝试一下修改Rts和Dts的值。
    我使用VS2005的SerialPort是不需要自己建立新线程的,控件自己建了一个,
    不过它的datareceived事件需要用线程间交互的方法与主进程通讯。