You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#窗体间列表数据传递问题:无法获取Form1列表最后元素

问题

我想在Form2中获取Form1里eaxListSM和eayListSM列表的最后一个元素,但试了多种方法(包括窗体引用)都返回Null。这两个列表存储的是从GY-521传感器获取的加速度信号,每50毫秒更新一次。请问用DataTransfer能不能得到正确结果?

Form1 代码

namespace WindowsFormsApp3
{
    public partial class Form1 : Form
    {
        private SerialPort serialPort;

        // 定义列表
        public static List<double> axList = new List<double>();
        public static List<double> ayList = new List<double>();

        // 定义信号处理相关变量
        IEnumerable<double> eaxList;
        IEnumerable<double> eayList;
        IEnumerable<double> eazList;
        IEnumerable<int> eroundedAccResultList;
        IEnumerable<int> eroundedGyroResultList;
        public static IEnumerable<double> eaxListSM;
        public static IEnumerable<double> eayListSM;
        IEnumerable<double> eazListSM;
        IEnumerable<double> eaxListDF;
        IEnumerable<double> eayListDF;
        IEnumerable<double> eazListDF;

        public Form1()
        {
            InitializeComponent();
            serialPort = new SerialPort("COM3", 9600);
            serialPort.DataReceived += SerialPort_DataReceived;
            Basketball.Click += Basketball_Click;
            this.BackColor = Color.LightBlue;
            Form2 newForm = new Form2(this);

            eaxList = axList;
            eayList = ayList;
            eazList = azList;
            eroundedAccResultList = roundedAccResultList;
            eroundedGyroResultList = roundedGyroResultList;

            try
            {
                serialPort.Open();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error opening serial port: " + ex.Message);
            }
        }

        private Form2 form2 = null;

        private void Basketball_Click(object sender, EventArgs e)
        {
 
            if (form2 == null || form2.IsDisposed)
            {
                Form2 form2 = new Form2(this);
                form2.FormClosed += (s, args) => form2 = null;
                form2.Show();
            }
            else
            {
                form2.Focus();
            }
        }
    }

    namespace Filtering
    {
        /// <summary>
        /// <para>实现Savitzky-Golay平滑滤波器,参考自[1]</para>
        /// <para>[1] Sophocles J.Orfanidis. 1995. Introduction to Signal Processing. Prentice-Hall, Inc., Upper Saddle River, NJ, USA.</para>
        /// </summary>
        public sealed class SavitzkyGolayFilter
        {
            private readonly int sidePoints;

            private Matrix<double> coefficients;

            public SavitzkyGolayFilter(int sidePoints, int polynomialOrder)
            {
                this.sidePoints = sidePoints;
                Design(polynomialOrder);
            }

            /// <summary>
            /// 对输入样本进行平滑处理
            /// </summary>
            /// <param name="samples"></param>
            /// <returns></returns>
            public double[] Process(double[] samples)
            {
                int length = samples.Length;
                double[] output = new double[length];
                int frameSize = (sidePoints << 1) + 1;
                double[] frame = new double[frameSize];

                Array.Copy(samples, frame, frameSize);

                for (int i = 0; i < sidePoints; ++i)
                {
                    output[i] = coefficients.Column(i).DotProduct(Vector<double>.Build.DenseOfArray(frame));
                }

                for (int n = sidePoints; n < length - sidePoints; ++n)
                {
                    Array.ConstrainedCopy(samples, n - sidePoints, frame, 0, frameSize);
                    output[n] = coefficients.Column(sidePoints).DotProduct(Vector<double>.Build.DenseOfArray(frame));
                }

                Array.ConstrainedCopy(samples, length - frameSize, frame, 0, frameSize);

                for (int i = 0; i < sidePoints; ++i)
                {
                    output[length - sidePoints + i] = coefficients.Column(sidePoints + 1 + i).DotProduct(Vector<double>.Build.Dense(frame));
                }

                return output;
            }

            private void Design(int polynomialOrder)
            {
                double[,] a = new double[(sidePoints << 1) + 1, polynomialOrder + 1];

                for (int m = -sidePoints; m <= sidePoints; ++m)
                {
                    for (int i = 0; i <= polynomialOrder; ++i)
                    {
                        a[m + sidePoints, i] = Math.Pow(m, i);
                    }
                }

                Matrix<double> s = Matrix<double>.Build.DenseOfArray(a);
                coefficients = s.Multiply(s.TransposeThisAndMultiply(s).Inverse()).Multiply(s.Transpose());
            }
        }

    }
}

Form2 代码

namespace WindowsFormsApp3
{
    public partial class Form2 : Form
    {
        private int ballX = 50;
        private int ballY = 50;
        private int ballSpeedX = 0;
        private int ballSpeedY = 0;
        private DateTime basketEntryTime;

        private Form1 parentForm;

        public Form2(Form1 parentForm)
        {
            InitializeComponent();
            Timer timer = new Timer();
            timer.Interval = 50;
            timer.Tick += new EventHandler(Update);
            timer.Start();

            this.parentForm = parentForm;

        }

     
        private void Form2_Load(object sender, EventArgs e)
        {
            double eaxValue = parentForm.eaxListSM.Last();
            double eayValue = parentForm.eayListSM.Last();

        }
    }
}

问题分析与解决方案

1. 核心问题:eaxListSM/eayListSM未初始化赋值

你遇到的Null问题和DataTransfer无关,根本原因是Form1中的eaxListSM和eayListSM仅被声明为静态IEnumerable变量,但从未被初始化或赋值。你需要在传感器数据更新后,对原始数据应用Savitzky-Golay滤波,并将结果赋值给这两个变量。

修复步骤:

  • 在Form1中添加滤波实例,并在数据更新时赋值:
    // 在Form1类中添加滤波实例(按需调整参数)
    private Filtering.SavitzkyGolayFilter sgFilter = new Filtering.SavitzkyGolayFilter(2, 2);
    
    // 在SerialPort_DataReceived事件中处理传感器数据
    private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        // 读取并解析传感器数据到axList、ayList的代码(你现有逻辑)
        // ...
    
        // 应用滤波并赋值给eaxListSM/eayListSM
        lock (axList) // 线程安全锁,避免多线程冲突
        {
            if (axList.Count > 0)
            {
                double[] axArray = axList.ToArray();
                Form1.eaxListSM = sgFilter.Process(axArray).ToList(); // 转为List避免延迟执行
            }
            if (ayList.Count > 0)
            {
                double[] ayArray = ayList.ToArray();
                Form1.eayListSM = sgFilter.Process(ayArray).ToList();
            }
        }
    }
    
  • 建议将eaxListSM和eayListSM的类型改为List<double>,而非IEnumerable<double>,避免延迟执行导致的重复计算和空引用风险:
    public static List<double> eaxListSM = new List<double>();
    public static List<double> eayListSM = new List<double>();
    

2. Form2中安全访问数据

Form2的Load事件可能在传感器数据还未更新、列表为空时触发,直接调用Last()会报错。建议在Timer的Tick事件中访问数据,同时处理线程安全:

private void Update(object sender, EventArgs e)
{
    // 跨线程访问UI控件时需要Invoke
    if (this.InvokeRequired)
    {
        this.Invoke(new Action(() => Update(sender, e)));
        return;
    }

    // 先判断列表是否有效
    if (parentForm.eaxListSM != null && parentForm.eaxListSM.Count > 0 
        && parentForm.eayListSM != null && parentForm.eayListSM.Count > 0)
    {
        double eaxValue = parentForm.eaxListSM.Last();
        double eayValue = parentForm.eayListSM.Last();
        
        // 用获取到的加速度值更新球的状态
        ballSpeedX = (int)(eaxValue * 10); // 按需调整转换系数
        ballSpeedY = (int)(eayValue * 10);
        ballX += ballSpeedX;
        ballY += ballSpeedY;
        
        // 刷新界面绘制
        this.Invalidate();
    }
}

3. DataTransfer的适用性

DataTransfer多用于跨进程、跨组件的数据传递,在同一Windows Forms应用的两个窗体间完全没必要使用。直接通过窗体引用或静态属性访问数据更高效,只要解决了列表初始化和赋值的问题,就能正常获取最新的传感器数据。


内容的提问来源于stack exchange,提问作者Hadis Seif

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 12:29:50