我正在尝试编写一个小型应用程序,它只是从套接字读取数据,从数据中提取一些信息(两个整数)并将提取的信息发送到串行端口上。
这个想法是它应该开始并继续前进。简而言之,它有效,但不会持续很长时间。在持续很短的一段时间后,我开始接收 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() 进入睡眠状态,我猜这是调用函数?并且没有产生预期的结果。
任何建议,将不胜感激。干杯。