首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >串口是否响应EventHandler,而不是ReadExisting或ReadLine?

串口是否响应EventHandler,而不是ReadExisting或ReadLine?
EN

Stack Overflow用户
提问于 2011-09-28 00:35:09
回答 7查看 8.4K关注 0票数 5

我有一个从c#串口读取数据的程序。我需要快速写入一个端口,从它读取,然后关闭它。我不能让它开着。我知道串行端口的读写速度很慢,我尝试将ReadTimeout和WriteTimeout属性设置为高,并添加了一个thread.Sleep来尝试拖动设备的读写超时。下面是一小段代码:

我的写入端口的方法:

代码语言:javascript
运行
复制
    private void CheckPorts(string testMessage)
    {

        foreach (string s in SerialPort.GetPortNames())
        {
            portNumber = Int32.Parse(s.Remove(0, 3));
            testSerial = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
            if (testSerial.IsOpen)
            {
                testSerial.Close();
            }
            testSerial.ReadTimeout = 2000;
            testSerial.WriteTimeout = 1000;
            testSerial.Open();
            if (testSerial.IsOpen)
            {
                string received;
                testSerial.DiscardInBuffer();
                try
                {
                    //testSerial.DataReceived += new SerialDataReceivedEventHandler(testSerialPort_DataReceived);

                    testSerial.Write(testMessage);
                    System.Threading.Thread.Sleep(2000);

                    received = testSerial.ReadExisting();  //EITHER I USE THIS OR EVENT HANDLER, NOT BOTH
                }
                catch (TimeoutException e)
                {
                    testSerial.Close();
                    continue;
                }

               if (received.Length > 0)
                {
                    MessageReceived(received);
                }
                testSerial.Close();
            }
       } 
 }



 private void testSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        string received = testSerial.ReadExisting();
        int y = received.IndexOf("\r");
        while (y == -1)
        {
            received = received + testSerial.ReadExisting();
            y = received.IndexOf("\r");
        }

        if (testSerial.IsOpen)
        {
            testSerial.Close();
        }

    }

我想知道,如果我一定要使用数据处理程序,我如何保持串行端口打开足够长的时间来读取它,但在下一个端口需要打开之前关闭串行端口?

看,第一个方法被调用了几次,它遍历foreach循环,在几个端口上尝试一条消息,然后尝试读取响应。因此,有时我必须关闭端口,否则下一次它通过它时,它不能正常工作,因为端口仍然是打开的

下面是我更新的代码(仍然不能工作):

代码语言:javascript
运行
复制
 private void CheckPorts(string testMessage, int baudRate)
    {

        foreach (string s in SerialPort.GetPortNames())
        {
            var interval = 3000; // ms 
            var timer = new System.Timers.Timer(interval);
            timer.Elapsed += (o, e) =>
            {
                timer.Enabled = false;

                if (testSerial.IsOpen)
                    testSerial.Close();  // may not be necessary with Dispose? 

                testSerial.Dispose();
                timer.Dispose();
            };

            portNumber = Int32.Parse(s.Remove(0, 3));
            testSerial = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
            testSerial.ReadTimeout = 2000;
            testSerial.WriteTimeout = 2000;
            if (testSerial.IsOpen)
            {
                testSerial.Close();
            }

            testSerial.Open();
            timer.Enabled = true; 

            if (testSerial.IsOpen)
            {
                string received;
                //testSerial.DiscardInBuffer();
                //autoEvent = new AutoResetEvent(false);
                try
                {
                   // testSerial.DataReceived += new SerialDataReceivedEventHandler(testSerialPort_DataReceived);

                  // autoEvent.Reset();
                    lblPortNum.Content = s;
                    lblPortNum.Refresh();

                    testSerial.Write(testMessage);
                    //System.Threading.Thread.Sleep(2000);

                    //testSerial.NewLine = "\r\n";
                    byte[] rBuff = new byte[2];
                    int rCnt = testSerial.Read(rBuff, 0, 2);
                    System.Text.Encoding enc = System.Text.Encoding.ASCII;
                    received = enc.GetString(rBuff);



                     //received = testSerial.ReadLine();
                }
                catch (TimeoutException e)
                {
                    testSerial.Close();
                    continue;
                }

               if (received.Length > 0)
               {
                    MessageReceived(received, Int16.Parse(s.Remove(0, 3)));
                }
                /*
                if (autoEvent.WaitOne(2000))
                {
                    // the port responded 
                   // testSerial.Close();
                    autoEvent.Dispose();
                    lblPortNum.Content = "HEY I RESPONDED";
                }
                else
                {
                    testSerial.Close();
                    autoEvent.Dispose();
                    continue;
                    // port did not respond within 2 seconds 
                }*/
              //testSerial.Close();
            }
        } 
     }

再次更新(仍无法正常工作)

代码语言:javascript
运行
复制
private void CheckPorts(string testMessage, int baudRate)
    {

        foreach (string s in SerialPort.GetPortNames())
        {
            portNumber = Int32.Parse(s.Remove(0, 3));

            // MUST BE LOCAL 
            var serialOneOfMany = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
            serialOneOfMany.ReadTimeout = 2000;
            serialOneOfMany.WriteTimeout = 2000;
            if (serialOneOfMany.IsOpen)
            {
                serialOneOfMany.Close();
            }

            // timer must be defined _after_ serialOneOfMany 
            var interval = 3000; // ms  
            var timer = new System.Timers.Timer(interval);
            timer.Elapsed += (o, e) =>
            {
                timer.Enabled = false;

                if (serialOneOfMany.IsOpen)
                    serialOneOfMany.Close();  // may not be necessary with Dispose?  

                serialOneOfMany.Dispose();
                timer.Dispose();
            };

            if (serialOneOfMany.IsOpen)
            {
                string received;

                try
                {
                    lblPortNum.Content = s;
                    lblPortNum.Refresh();

                    serialOneOfMany.Write(testMessage);
                    byte[] rBuff = new byte[2];
                    int rCnt = serialOneOfMany.Read(rBuff, 0, 2);
                    System.Text.Encoding enc = System.Text.Encoding.ASCII;
                    received = enc.GetString(rBuff);

                }
                catch (TimeoutException e)
                {
                    serialOneOfMany.Close();
                    continue;
                }

                if (received.Length > 0)
                {
                    CheckIfTheMessageMatches(received, Int16.Parse(s.Remove(0, 3)));
                }

            }
        } 

    }

所以有了这个更新,它就会遍历代码,我可以逐行遍历代码,但它根本不会停止3秒。如果我在没有任何调试中断的情况下运行它,它只会在不到一秒的时间内通过它

更新10-25-11

代码语言:javascript
运行
复制
 private void CheckPorts(string testMessage, int baudRate)
    {
        foreach (string s in SerialPort.GetPortNames())
        {
            string received = "";
            testSerial = new SerialPort(s,baudRate, Parity.None, 8, StopBits.One);

            lblStatus.Content = "Scanning...";
            lblStatus.Refresh();

            if (testSerial.IsOpen)
            {
                testSerial.Close();
            }
            else
            {
                testSerial.Open();
            }

            if (testSerial.IsOpen)
            {
                try
                {
                    testSerial.NewLine = "\r";
                    lblPortNum.Content = s;
                    lblPortNum.Refresh();
                    testSerial.WriteTimeout= 500;
                    testSerial.ReadTimeout = 1000;
                    testSerial.WriteLine(testMessage);

                    System.Threading.Thread.Sleep(500);

                    /*THIS DOESN'T WORK
                    byte[] buffer = new byte[testSerial.BytesToRead];
                    int rCnt = testSerial.Read(buffer, 0, buffer.Length);
                    received = enc.GetString(buffer);*/

                    //received = Convert.ToString(testSerial.BaseStream.Read(buffer, 0, (int)buffer.Length));


                    received =  testSerial.ReadLine();


                   int y = received.IndexOf("\r");
                   while (y == -1)
                   {
                       received = received + testSerial.ReadExisting();
                       y = received.Length;
                   }

                   if (lblInfo.Dispatcher.Thread == Thread.CurrentThread)
                   {
                       CheckIfTheMessageMatches(received, s);
                       received = received + lblInfo.Content;
                       lblInfo.Content = received;
                   }
                   else
                   {
                       lblInfo.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadCheck(threadCheck), received);
                   }
                   if (testSerial.IsOpen)
                   {
                       testSerial.Close();
                   }

                    /*I USE THIS WITH THE sPort.Read() METHOD
                    while (rCnt > 0)
                    {
                        if (lblInfo.Dispatcher.Thread == Thread.CurrentThread)
                        {
                            CheckIfTheMessageMatches(received, s);
                            rCnt = 0;
                            received = received + lblInfo.Content;
                            lblInfo.Content = received;                                
                        }

                        else
                        {
                            lblInfo.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadCheck(threadCheck), received);
                        }
                    }
                     */

                   if (testSerial.IsOpen)
                   {
                       testSerial.Close();
                   }

                }
                catch (TimeoutException e)
                {
                    testSerial.Close();
                    continue;
                }
                received = null;
            }
        } 

        lblStatus.Content = "Finished Scanning.";
        lblPortNum.Content = "";
    }

更新代码这里有一些新的代码,仍然不能工作,dataeventhandler甚至没有调用过一次。我知道它收到了消息,因为我有另一个程序可以处理串行设备

代码语言:javascript
运行
复制
private void CheckPorts(string testMessage, int baudRate)
    {
        foreach (string s in SerialPort.GetPortNames())
        {
            var serialOneOfMany = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
            serialOneOfMany.ReadTimeout = 700;
            serialOneOfMany.WriteTimeout = 100;

            var interval = 500; // ms
            var timer = new System.Timers.Timer(interval);
            timer.Elapsed += (o, e) =>
            {
                timer.Enabled = false;

                if (serialOneOfMany.IsOpen)
                    serialOneOfMany.Close();  // may not be necessary with Dispose?

                serialOneOfMany.Dispose();
                timer.Dispose();
            };
            timer.Enabled = true;

            lblStatus.Content = "Scanning...";
            lblStatus.Refresh();

            if (serialOneOfMany.IsOpen)
            {
                serialOneOfMany.Close();
            }
            else
            {
                serialOneOfMany.Open();
            }

            if (serialOneOfMany.IsOpen)
            {
                string received;

                try
                {
                    lblPortNum.Content = s;
                    lblPortNum.Refresh();

                    serialOneOfMany.WriteLine(testMessage);
                    System.Threading.Thread.Sleep(400);
                    serialOneOfMany.DataReceived += new SerialDataReceivedEventHandler(testSerialPort_DataReceived);

                }
                catch (TimeoutException e)
                {
                    serialOneOfMany.Close();
                    continue;
                }
            }
        } 

        lblStatus.Content = "Finished Scanning.";
        lblPortNum.Content = "";
    }

    private void testSerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        SerialPort receivingSerial = sender as SerialPort;
        string received = receivingSerial.ReadExisting();
        int y = received.IndexOf("\r");
        while (y == -1)
        {
            received = received + receivingSerial.ReadExisting();
            y = received.IndexOf("\r");
        }

        if (lblInfo.Dispatcher.Thread == Thread.CurrentThread)
        {
            string name = receivingSerial.PortName;
            received = received + lblInfo.Content;
            lblInfo.Content = received;
            CheckIfTheMessageMatches(received, name);
        }
        else
        {
            lblInfo.Dispatcher.Invoke(DispatcherPriority.Normal, new ThreadCheck(threadCheck), received);
        } 
        if (receivingSerial.IsOpen)
        {
            receivingSerial.Close();
        }

    }
EN

Stack Overflow用户

发布于 2011-10-29 00:01:47

请看一下这个(我还在answer中使用了一个与串行端口相关的问题,由darthwillard提出)。所有端口一个接一个地打开,DataReceived事件被绑定(您需要做的所有事情就是测试传入的消息),但不需要等待。定时器事件处理程序可以关闭所有端口或保留您想要使用的端口,等等。我希望它能有所帮助!

代码语言:javascript
运行
复制
private List<SerialPort> openPorts = new List<SerialPort>();

private void button3_Click(object sender, EventArgs e)
{
    int baudRate = 9600;
    string testMessage = "test";
    txtPortName.Text = "Testing all serial ports";
    foreach (string s in SerialPort.GetPortNames())
    {
        SerialPort newPort = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One);
        if (!newPort.IsOpen)
        {
            try
            {
                newPort.Open();
            }
            catch { }
        }
        if (newPort.IsOpen)
        {
            openPorts.Add(newPort);
            newPort.DataReceived += new SerialDataReceivedEventHandler(serialOneOfMany_DataReceived);
            newPort.Write(testMessage);
        }
        else
        {
            newPort.Dispose();
        }
    }
    txtPortName.Text = "Waiting for response";
    tmrPortTest.Enabled = true;
}

private void serialOneOfMany_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    txtPortName.Text = ((SerialPort)sender).PortName;
}

private void tmrPortTest_Tick(object sender, EventArgs e)
{
    tmrPortTest.Enabled = false;
    foreach (SerialPort port in openPorts)
    {
        if (port.PortName != txtPortName.Text)
        {
            port.Close();
            port.Dispose();
        }
    }
}
票数 1
EN
查看全部 7 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7572596

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档