C# 串行COM端口仅在调试时工作
我有比赛条件或者类似的情况。我的意思是,如果我在从COM读取之前切换一个断点,一切都很好。但是当我把它关掉的时候,它会冻结。写作:C# 串行COM端口仅在调试时工作,c#,.net,multithreading,serial-port,race-condition,C#,.net,Multithreading,Serial Port,Race Condition,我有比赛条件或者类似的情况。我的意思是,如果我在从COM读取之前切换一个断点,一切都很好。但是当我把它关掉的时候,它会冻结。写作: public void Send(ComMessage message) { byte[] bytes = message.Serialise(); if (!_outputPort.IsOpen) _outputPort.Open(); try {
public void Send(ComMessage message)
{
byte[] bytes = message.Serialise();
if (!_outputPort.IsOpen)
_outputPort.Open();
try
{
byte[] size = BitConverter.GetBytes(bytes.Length);
_outputPort.Write(size, 0, size.Length);
_outputPort.Write(bytes, 0, bytes.Length);
}
finally
{
if (_outputPort != _inputPort)
_outputPort.Close();
}
}
阅读
private void InputPortOnDataReceived(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)
{
var port = (SerialPort) sender;
byte[] sizeBuffer = new byte[sizeof(long)];
port.Read(sizeBuffer, 0, sizeBuffer.Length);
int length = BitConverter.ToInt32(sizeBuffer, 0);
byte[] buffer = new byte[length];
int i = 0;
while (i < length)
{
int readed = port.Read(buffer, i, length - i);
i += readed;
}
var message = ComMessage.Deserialize(buffer);
MessageReceived(this, message);
}
private void InputPortOnDataReceived(对象发送方,SerialDataReceivedEventArgs SerialDataReceivedEventArgs)
{
var port=(SerialPort)发送方;
字节[]sizeBuffer=新字节[sizeof(长)];
读取端口(sizeBuffer,0,sizeBuffer.Length);
int length=BitConverter.ToInt32(sizeBuffer,0);
字节[]缓冲区=新字节[长度];
int i=0;
while(i
例如,消息的长度为625字节。如果我切换断点,port.BytesToRead
等于625,但如果我禁用它,字节计数为621
奇怪的是,它只适用于少量字节(对于短消息),但不适用于很长时间
请给我一些建议
消息的长度为625字节。如果我切换断点,
port.BytesToRead等于625,但如果禁用它,字节计数为621
您从未检查第一次读取的以查看它读取了多少字节。它在中的读取量可能小于sizeof(long)
字节。但是,这并不是问题的根源,主要问题是您正在生成一个大小为long
的缓冲区,但long是Int64
,您正在调用ToInt32
(并在发送方中写入Int32
)
字节计数为261而不是265的原因是消息的前4个字节位于sizeBuffer[4]
到sizeBuffer[7]
中,而您从未处理过这些字节
要解决此问题,您应该执行sizeof(int)
或更好的操作,使缓冲区更明显地用于ToInt32
调用,使用sizeof(Int32)
读取并不保证您读取sizeBuffer.Length
字节。您需要从Read返回int并使用它。无法保证在一端发送的内容将作为另一端的一条消息接收。Send()方法已严重损坏,关闭端口会丢弃传输缓冲区的内容。它在调试时工作,因为在关闭端口之前,您给驱动程序足够的时间清空缓冲区。Close()还有更多问题,请阅读MSDN文章。样板文件只在程序初始化时调用Open(),在程序结束前不调用Close()。@ScottChamberlain我编辑过,但这个版本不能正常工作too@HansPassant谢谢,我来试试。因为我认为我应该像与db连接一样与它进行交互-只有在传输更新版本的数据时才打开和关闭,您仍然不会检查第一次读取的来查看它读取了多少字节。它在中的读取量可能小于sizeof(long)
字节。另外,您正在创建一个大小为long
的缓冲区,但long是Int64
,您正在调用到int32
。您应该做sizeof(int)
或者做得更好,以使其更明显sizeof(Int32)