0

我正在尝试编写一个小型应用程序,它只是从套接字读取数据,从数据中提取一些信息(两个整数)并将提取的信息发送到串行端口上。

这个想法是它应该开始并继续前进。简而言之,它有效,但不会持续很长时间。在持续很短的一段时间后,我开始接收 IOExceptions 并且套接字接收缓冲区被淹没。

线程框架取自 MSDN 串口示例。

send() 中的延迟 readThread.Join() 是为了延迟 read() 以便有机会发生串行端口中断处理,但我认为我误解了 join 函数。我要么需要更有效地同步进程,要么在数据从套接字进入时丢弃一些数据,这很好。整数数据正在控制一个云台单元,我确信每秒四次是可以接受的,但不确定如何最好地实现,任何想法都将不胜感激,欢呼。

using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.IO;


namespace ConsoleApplication1
{
    class Program
    {
        static bool _continue;
        static SerialPort _serialPort;
        static Thread readThread;
        static Thread sendThread;
        static String sendString;
        static Socket s;
        static int byteCount;
        static Byte[] bytesReceived;

        // synchronise send and receive threads
        static bool dataReceived;

        const int FIONREAD = 0x4004667F;

        static void Main(string[] args)
        {
            dataReceived = false;
            readThread = new Thread(Read);
            sendThread = new Thread(Send);

            bytesReceived = new Byte[16384];

            // Create a new SerialPort object with default settings.
            _serialPort = new SerialPort("COM4", 38400, Parity.None, 8, StopBits.One);

            // Set the read/write timeouts
            _serialPort.WriteTimeout = 500;

            _serialPort.Open();
            string moveMode = "CV ";
            _serialPort.WriteLine(moveMode);

            s = null;
            IPHostEntry hostEntry = Dns.GetHostEntry("localhost");
            foreach (IPAddress address in hostEntry.AddressList)
            {
                IPEndPoint ipe = new IPEndPoint(address, 10001);
                Socket tempSocket =
                    new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

                tempSocket.Connect(ipe);

                if (tempSocket.Connected)
                {
                    s = tempSocket;
                    s.ReceiveBufferSize = 16384;
                    break;
                }
                else
                {
                    continue;
                }
            }

            readThread.Start();
            sendThread.Start();

            while (_continue)
            {
                Thread.Sleep(10);
                ;// Console.WriteLine("main...");
            }

            readThread.Join();
            _serialPort.Close();
            s.Close();
        }

        public static void Read()
        {
            while (_continue)
            {
                try
                {
                    //Console.WriteLine("Read");
                    if (!dataReceived)
                    {
                        byte[] outValue = BitConverter.GetBytes(0);
                        // Check how many bytes have been received.
                        s.IOControl(FIONREAD, null, outValue);
                        uint bytesAvailable = BitConverter.ToUInt32(outValue, 0);

                        if (bytesAvailable > 0)
                        {
                            Console.WriteLine("Read thread..." + bytesAvailable);
                            byteCount = s.Receive(bytesReceived);
                            string str = Encoding.ASCII.GetString(bytesReceived);
                            //str = Encoding::UTF8->GetString( bytesReceived );
                            string[] split = str.Split(new Char[] { '\t', '\r', '\n' });

                            string filteredX = (split.GetValue(7)).ToString();
                            string filteredY = (split.GetValue(8)).ToString();

                            string[] AzSplit = filteredX.Split(new Char[] { '.' });
                            filteredX = (AzSplit.GetValue(0)).ToString();
                            string[] ElSplit = filteredY.Split(new Char[] { '.' });
                            filteredY = (ElSplit.GetValue(0)).ToString();

                            // scale values 
                            int x = (int)(Convert.ToInt32(filteredX) * 1.9);
                            string scaledAz = x.ToString();
                            int y = (int)(Convert.ToInt32(filteredY) * 1.9);
                            string scaledEl = y.ToString();

                            String moveAz = "PS" + scaledAz + " ";
                            String moveEl = "TS" + scaledEl + " ";

                            sendString = moveAz + moveEl;
                            dataReceived = true;
                        }
                    }
                }
                catch (TimeoutException) {Console.WriteLine("timeout exception");}
                catch (NullReferenceException) {Console.WriteLine("Read NULL reference  exception");}
            }
        }

        public static void Send()
        {
            while (_continue)
            {
                try
                {
                    if (dataReceived)
                    {
                        // sleep Read() thread to allow serial port interrupt     processing 
                        readThread.Join(100);
                        // send command to PTU
            dataReceived = false;
                        Console.WriteLine(sendString);
                        _serialPort.WriteLine(sendString);
                    }
                }
                catch (TimeoutException) { Console.WriteLine("Timeout exception"); }
                catch (IOException) { Console.WriteLine("IOException exception"); }
                catch (NullReferenceException) { Console.WriteLine("Send NULL reference exception"); }
            }
        }
    }
}

更新:

感谢乔恩的回复。

我正在尝试做的是轮询一个套接字以获取数据,如果它在那里处理它并将其发送到串行端口,否则继续轮询套接字,重复整个过程并令人作呕。

我最初的尝试使用了一个线程并且我遇到了同样的问题,这让我相信我需要给串口一些更多的时间来允许它在下一个循环中给它更多数据之前发送数据,因为有一次我已经将数据发送到串行端口,我非常努力地轮询套接字。已经说过 IOExceptions 在大约 30 秒的操作后发生,可能我的意思是我应该立即看到 IOExceptions?

我认为,我对 join 函数的解释是不正确的,理想情况下,从 send() 调用 readThread.Join 将允许 read() 在仍然泵送 COM 端口的同时进入睡眠状态,但我认为它似乎让 send() 进入睡眠状态,我猜这是调用函数?并且没有产生预期的结果。

任何建议,将不胜感激。干杯。

4

2 回答 2

2

我最近也遇到过这个问题(很多其他人也遇到过)——基本上是微软的串口初始化代码的问题。如果您想了解更多信息,我在这里写了一个非常详细的解释。我还建议了一个解决方法。希望对这个问题有足够的大惊小怪,以便微软会注意到并尽快修复它 - 也许是 .NET 4.0 修补程序。从 .NET 2.0 开始,这个问题已经持续了足够长的时间(第一次引入 System.IO.Ports 命名空间)。

于 2010-07-05T00:23:25.287 回答
1

看起来您正在尝试做的是发送一些数据,然后等待响应,然后重复。您为此使用了两个线程并尝试同步它们。我认为你只需要一个线程。首先发送,然后等待响应,然后重复。这将消除您的线程同步问题。

于 2009-06-10T13:35:39.487 回答