C# 串行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 {

我有比赛条件或者类似的情况。我的意思是,如果我在从COM读取之前切换一个断点,一切都很好。但是当我把它关掉的时候,它会冻结。写作:

    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)