启动WinForm应用时抛出System.StackOverflowException异常求助
异常触发原因
- Form1类在定义字段时直接实例化了
Zombie zombie = new Zombie();,程序启动创建Form1主窗体实例时,会优先初始化该Zombie对象 - Zombie类在定义字段时直接实例化了
Form1 Test = new Form1();,创建Zombie实例时,又会触发新的Form1对象初始化 - 二者形成无限递归的实例化调用,栈内存被不断占用最终抛出
System.StackOverflowException
修复步骤
- 删掉Zombie类中
Form1 Test = new Form1();这行代码,不要自行创建新的主窗体实例,而是复用已经存在的主窗体对象 - 给Zombie类增加一个
Form1类型的成员变量,用来保存传入的主窗体实例 - 修改
zombie_Click事件逻辑,使用保存的主窗体实例操作控件 - (可选优化)修改Form1中和类重名的
Zombie()方法名,避免语法歧义,比如改为MoveZombie()
修改后的完整代码
Zombie类代码
using System; using System.Drawing; using System.Windows.Forms; namespace Tester { class Zombie { Random random = new Random(); // 新增成员变量存储主窗体实例 private Form1 _mainForm; private int score = 0; public void MakeZombie(int aantal, Form1 formInstance) { // 保存传入的主窗体实例 _mainForm = formInstance; for (int i = 0; i < aantal; i++) { PictureBox picture = new PictureBox(); picture.Image = Properties.Resources.ZombieDik; picture.Size = new Size(200, 200); picture.Location = new Point(random.Next(1500), 0); picture.SizeMode = PictureBoxSizeMode.Zoom; picture.Click += zombie_Click; picture.BackColor = Color.Transparent; formInstance.Controls.Add(picture); } } void zombie_Click(object sender, EventArgs e) { PictureBox pic = sender as PictureBox; pic.Visible = false; score++; // 使用保存的主窗体实例操作控件 _mainForm.label2.Text = $"Score: {score}"; _mainForm.Controls.Remove(pic); pic.Dispose(); } } }
Form1类调整点
// 方法名修改避免和Zombie类重名 public void MoveZombie() { foreach (Control control in Controls) { PictureBox pic = control as PictureBox; if (pic != null) { pic.Top += 1; if (pic.Top > 600 && pic.Visible == true) { pic.Top = 0; test1.Text = $"Levens: {--levens}"; } else if (pic.Top > 600 && pic.Visible == false) { pic.Visible = true; pic.Top = 0; } } } } private void timer1_Tick(object sender, EventArgs e) { // 直接传当前主窗体实例 zombie.MakeZombie(5, this); }
额外注意
如果你的label2控件是Form1的私有控件,需要把它的Modifiers属性改为Public,或者在Form1里封装一个公开的修改分数的方法,Zombie类调用该方法更新分数,更符合封装规范。
内容的提问来源于stack exchange,提问作者Meadas
相关产品推荐
相关产品推荐

