C# Foreach在一段时间后停止查找动态创建的控件。调整窗口大小使其再次工作。为什么?我怎样才能修好它?

C# Foreach在一段时间后停止查找动态创建的控件。调整窗口大小使其再次工作。为什么?我怎样才能修好它?,c#,winforms,C#,Winforms,我是一名新的c#程序员,目前在课堂上,我一直在做这个副题,它(某种程度上)准确地表示弹跳球。我还希望它能够处理鼠标点击创建的球。我已经做了所有这些,它的工作,几秒钟。原始球始终工作,并且始终反弹/滚动。在鼠标单击时创建的动态创建的球将跳跃并滚动一段时间,但是当我使用的foreach语句停止识别它们时,它们都会冻结(不是同时冻结)。奇怪的是,当使用底部调整窗口大小时,它们又开始工作了。我是否遗漏了什么,或者这是一个我无法修复的错误?这是表单代码和设计器代码。如果你还需要什么,请告诉我 using

我是一名新的c#程序员,目前在课堂上,我一直在做这个副题,它(某种程度上)准确地表示弹跳球。我还希望它能够处理鼠标点击创建的球。我已经做了所有这些,它的工作,几秒钟。原始球始终工作,并且始终反弹/滚动。在鼠标单击时创建的动态创建的球将跳跃并滚动一段时间,但是当我使用的foreach语句停止识别它们时,它们都会冻结(不是同时冻结)。奇怪的是,当使用底部调整窗口大小时,它们又开始工作了。我是否遗漏了什么,或者这是一个我无法修复的错误?这是表单代码和设计器代码。如果你还需要什么,请告诉我

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace testBouncingBallMulti
{
    public partial class Form1 : Form
    {
        const int INITY = 0;
        const int INITX = 3;
        const int GRAVITY = 1;

        public Form1()
        {
            InitializeComponent();
            this.ball0.Tag = new Point(INITX, INITY);
        }

        byte counter = 1;

        private void createBall(object sender, MouseEventArgs e)
        {
            Label l = new Label();
            l.BackColor = System.Drawing.Color.Black;
            l.Location = new Point(MousePosition.X - this.Left, MousePosition.Y - this.Top);
            this.Controls.Add(l);
            l.Size = new System.Drawing.Size(15, 15);
            l.Tag = new Point(INITX, INITY);
            l.Name = "ball" + Convert.ToString(counter);
            counter++;
        }

        private void physicsLoop1(object sender, EventArgs e)
        {
            foreach (var ball in this.Controls.OfType<Label>())
            {
                moveBall(ball);
                bounce(ball);

                Point? init = ball.Tag as Point?;
                Point velocities = init.GetValueOrDefault(new Point(0, 0));
                if (velocities.Y == 0 && ball.Location.Y >= ClientSize.Height - 15)
                {
                    return;
                }
                velocities.Y = velocities.Y + GRAVITY;

                ball.Tag = new Point(velocities.X, velocities.Y);
            }
        }



        private void moveBall(Control ball)
        {
            Point? init = ball.Tag as Point?;
            Point velocities = init.GetValueOrDefault(new Point(0,0));

            ball.Location = new Point(ball.Location.X + velocities.X, ball.Location.Y + velocities.Y);
        }

        private void bounce(Control ball)
        {
            Point? init = ball.Tag as Point?;
            Point velocities = init.GetValueOrDefault(new Point(0,0));

            if (ball.Location.Y >= ClientSize.Height - 15)
            {
                if (velocities.Y == 0 && ball.Location.Y >= ClientSize.Height - 15)
                {
                }
                else if (ball.Location.Y > ClientSize.Height - 15)
                {
                    ball.Location = new Point(ball.Location.X, ClientSize.Height - 15);
                    velocities.Y = -(velocities.Y - 2);
                }
            }

            if (ball.Location.X >= ClientSize.Width - 15)
            {
                velocities.X = -(velocities.X);
            }

            if (ball.Location.X <= 0)
            {
                ball.Location = new Point(0, ball.Location.Y);
                velocities.X = -(velocities.X);
            }

            ball.Tag = new Point(velocities.X, velocities.Y);
        }

        private void physicsLoop2(object sender, EventArgs e)
        {

        }

        private void physicsLoop3(object sender, EventArgs e)
        {

        }
    }
}
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用系统数据;
使用系统图;
使用System.Linq;
使用系统文本;
使用System.Windows.Forms;
命名空间testBouncingBallMulti
{
公共部分类Form1:Form
{
常数int=0;
常数int INITX=3;
重力常数=1;
公共表格1()
{
初始化组件();
this.ball0.Tag=新点(INITX,INITY);
}
字节计数器=1;
私有void createBall(对象发送器,MouseEventArgs e)
{
标签l=新标签();
l、 BackColor=System.Drawing.Color.Black;
l、 位置=新点(MousePosition.X-this.Left,MousePosition.Y-this.Top);
本.控件.添加(l);
l、 尺寸=新系统图纸尺寸(15,15);
l、 标记=新点(INITX,INITY);
l、 Name=“ball”+转换为字符串(计数器);
计数器++;
}
私有void physicslop1(对象发送方,事件参数e)
{
foreach(this.Controls.OfType()中的var ball)
{
移动球;
弹跳(球);
点?初始=球。标记为点?;
点速度=初始GetValuerDefault(新点(0,0));
if(速度.Y==0&&ball.Location.Y>=ClientSize.Height-15)
{
返回;
}
速度.Y=速度.Y+重力;
ball.Tag=新点(速度.X,速度.Y);
}
}
专用空心移动球(控制球)
{
点?初始=球。标记为点?;
点速度=初始GetValuerDefault(新点(0,0));
ball.Location=新点(ball.Location.X+速度.X,ball.Location.Y+速度.Y);
}
私人空间弹跳(控制球)
{
点?初始=球。标记为点?;
点速度=初始GetValuerDefault(新点(0,0));
if(ball.Location.Y>=ClientSize.Height-15)
{
if(速度.Y==0&&ball.Location.Y>=ClientSize.Height-15)
{
}
else if(ball.Location.Y>ClientSize.Height-15)
{
ball.Location=新点(ball.Location.X,ClientSize.Height-15);
速度Y=-(速度Y-2);
}
}
if(ball.Location.X>=ClientSize.Width-15)
{
速度X=-(速度X);
}

如果(ball.Location.X您需要在标签移动过程中留出一些喘息的空间来重新绘制表单。请使用最佳做法,将您的绘制放在线程中,或者至少在计时器循环中处理一两条windows消息。

替换
返回
继续

if (velocities.Y == 0 && ball.Location.Y >= ClientSize.Height - 15)
{
    return;
}

我刚刚测试了你的Application.DoEvents()解决方案,结果仍然一样,所有非原始标签都冻结了。你说这幅画是什么意思?请永远不要使用
Application.DoEvents()
。它仅在.NET framework中用于VB6应用程序的向后兼容性。
DoEvents
可能会导致各种重新进入问题,应避免引入错误。当您向表单添加新控件时,它需要使表单或父控件无效和/或重新绘制。在应用程序中,您做得太多了。您必须ed用于处理(Windows)消息。您可以在窗体上放置WND_消息循环。这类似于Application.DoEvents。@enigmativity如果我突出显示了它会更好吗请将繁忙的“绘制到线程中”,在主线程之外。是否要将线程概念解释为标签在没有喘息空间的计时器上移动的情况?我确实提到了最佳实践。如果您根本没有提到
DoEvents
,或者甚至可能说不要使用
DoEvents
this.timer1.Interval=2,会更好0;
您的间隔太快;您的消息泵肯定已饱和。请将其至少增加到50。您甚至可能希望在
physicsLoop1()的开头关闭
timer1
,然后在底部重新打开它。我同意Jacob的观点,
return
可能不是您想要的。而不是使用
this.Controls.OfType()
,维护你自己的
列表
并反复查看。你尝试过雅各布的解决方案吗?谢谢你,这奏效了,我觉得自己像个白痴,没有早点意识到。我感谢你的帮助!
if (velocities.Y == 0 && ball.Location.Y >= ClientSize.Height - 15)
{
    return;
}