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
相关产品推荐
相关产品推荐

