首页 > 解决方案 > 将不断读取的串行缓冲区数据传递给另一个类的问题

问题描述

长话短说。; 我有一个名为 Scope 的类。并且此类包含范围操作等的所有逻辑。它还启动不断读取串行端口数据的后台线程(在我的情况下事件是不可靠的):

  Thread BackgroundReader = new Thread(ReadBuffer);
    BackgroundReader.IsBackground = true;
    BackgroundReader.Start();

  private void ReadBuffer()
        {
            SerialPort.DiscardInBuffer();
            while (!_stopCapture)
            {
                int bufferSize = SerialPort.BytesToRead;
                byte[] buffer = new byte[bufferSize];
                if(bufferSize > 5)
                {
                    SerialPort.Read(buffer, 0, bufferSize);
                    Port_DataReceivedEvent(buffer, null);
                }
                Thread.Sleep(_readDelay);
            }
            CurrentBuffer = null;
        }

在 Scope 类中有一个名为 Buffer 的公共字段

public byte[] Buffer
        {
          get
            {
                return CurrentBuffer;
            }
        }

这是在读取新数据时触发的事件

 private void Port_DataReceivedEvent(object sender, EventArgs e)
        {
            //populate buffer
            Info(sender, null);
            CurrentBuffer = ((byte[])sender);

            foreach(byte data in CurrentBuffer)
            {
                DataBuffer.Enqueue(data);
            }

            if (DataBuffer.Count() > _recordLength)
            {
                GenerateFrame(DataBuffer.ToArray());
                DataBuffer.Clear(); ;
            }
        }

为了使代码更易于管理,我将其拆分为几个类。其中一个类用于在当前流中搜索特定的数据模式并从该数据中创建特定的对象。此代码以发送到串行端口特定命令并期望返回帧的方式工作。如果没有收到reponse或者没有ok,就一次又一次的send,直到正确的response到达或者超时。响应预计在当前缓冲区中。那些奇怪的字符串操作是出于调试目的。

public class GetAcknowledgedFrame
    {
        byte[] WritedData;
        string lastEx;
        string stringData;

        public DataFrame WriteAcknowledged(Type SendType, Type ReturnType, JyeScope scope)
        {
            var stopwatch = new Stopwatch();
            stopwatch.Restart();
            while (stopwatch.ElapsedMilliseconds < scope.TimeoutTime)
            {
                try
                {
                    if (SendType == typeof(GetParameters))
                    {
                        WriteFrame(new ScopeControlFrames.GetParameters(), scope.SerialPort);
                    }
                    else if(SendType == typeof(GetConfig))
                    {
                        WriteFrame(new ScopeControlFrames.GetConfig(), scope.SerialPort);
                    }
                    else if (SendType == typeof(EnterUSBScopeMode))
                    {
                        WriteFrame(new ScopeControlFrames.EnterUSBScopeMode(), scope.SerialPort);
                    }
                    return ReturnFrame(ReturnType, scope.Buffer, scope.TimeoutTime);
                }
                catch (InvalidDataFrameException ex)
                {
                    lastEx = ex.Message;
                    System.Threading.Thread.Sleep(10);
                }
            }
            stringData = "";
            foreach (var data in scope.Buffer)
            {
                stringData += data + ",";
            }
            stringData.Remove(stringData.Length - 1);
            throw new TimeoutException($"Timeout while waiting for frame acknowledge: " + SendType.ToString() + ", " + ReturnType.ToString() + Environment.NewLine+ "Add. err: "+lastEx);
        }


        private DataFrame ReturnFrame(Type FrameType, byte[] buffer, int timeoutTime)
        {
            if (FrameType == typeof(DataFrames.DSO068.CurrConfigDataFrame))
            {
                DataFrames.DSO068.CurrConfigDataFrame CurrConfig = new DataFrames.DSO068.CurrConfigDataFrame(buffer);
                return CurrConfig;
            }
            else if (FrameType == typeof(DataFrames.DSO112.CurrConfigDataFrame))
            {
                DataFrames.DSO112.CurrConfigDataFrame CurrParam = new DataFrames.DSO112.CurrConfigDataFrame(buffer);
                return CurrParam;
            }
            else if (FrameType == typeof(CurrParamDataFrame))
            {
                CurrParamDataFrame CurrParam = new CurrParamDataFrame(buffer);
                return CurrParam;
            }
            else if (FrameType == typeof(DataBlockDataFrame))
            {
                DataBlockDataFrame CurrData = new DataBlockDataFrame(buffer);
                return CurrData;
            }
            else if (FrameType == typeof(DataSampleDataFrame))
            {
                DataSampleDataFrame CurrData = new DataSampleDataFrame(buffer);
                return CurrData;
            }
            else if (FrameType == typeof(ScopeControlFrames.ScopeReady))
            {
                ScopeControlFrames.ScopeReady ready = new ScopeControlFrames.ScopeReady(buffer);
                return ready;
            }
            else
            {
                throw new InvalidOperationException("Wrong object type");
            }
        }

        private bool WriteFrame(DataFrame frame, IStreamResource port)
        {
            WritedData = frame.Data;
            port.Write(frame.Data, 0, frame.Data.Count());
            return true;
        }
    }

从主类(和主线程)我调用这个类中的方法,例如:

 var Ready = (ScopeControlFrames.ScopeReady)new GetAcknowledgedFrame().WriteAcknowledged
                            (typeof(ScopeControlFrames.EnterUSBScopeMode), typeof(ScopeControlFrames.ScopeReady), this);

问题是当我将“this”对象(具有在后台工作的线程)传递给我的助手类时。似乎帮助类看不到此对象中的更改数据。当我将助手类的代码与主类分开时,问题就开始了。我的问题: - 我知道对象是通过引用传递的,这意味着我认为当对象动态改变其状态时(在这种情况下,数据缓冲区应该在接收新数据时改变)所有引用该对象的类也都在看到这改变了。也许我错过了什么?- 我尝试传递数组(通过引用),数组也是引用类型。但这对我一点帮助都没有。也许我错过了什么?我尝试将此类更改为静态,但没有帮助。非常感谢您的帮助。

标签: c#serial-port

解决方案


下面的代码;

Info(sender, null);
CurrentBuffer = ((byte[])sender);

正在创建一个名为 CurrentBuffer 的新引用变量。在这行代码之前持有指向 CurrentBuffer 值的引用“指针”的任何其他代码在重置时都不会获得 CurrentBuffer 的新值。


推荐阅读