将不断读取串行缓冲区数据传递给另一个类的问题

时间:2018-09-03 20:13:03

标签: c# serial-port

长话短说。 ; 我有一个名为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(); ;
            }
        }

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

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

1 个答案:

答案 0 :(得分:1)

下面的代码;

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

正在创建一个称为CurrentBuffer的新参考变量。重置此代码之前,在此代码行之前持有对CurrentBuffer值的引用“指针”的任何其他代码都不会获得CurrentBuffer的新值。