如何在C# WinForms程序中的while循环之前更改图像外观?

8wtpewkr  于 2023-05-29  发布在  C#
关注(0)|答案(1)|浏览(160)

窗体在while(int<10)语句之前没有运行脚本。
我试图做一个程序,改变图片盒的图像之前抖动周围的屏幕有点。(笑话/测试程序,编码新手)
由于某种原因,它直到最后才改变图像的外观,而不是在While循环之前。
这里是代码的重要部分,随机值是全局值。

private void PictureBox1_Click(object sender, EventArgs e)
        {
            imgPeter.Image = Properties.Resources.retep; //why does this not work?!
            touhou = 0;
            while (touhou < 10)
            {
                int x = rnd.Next(0, (System.Windows.Forms.SystemInformation.PrimaryMonitorSize.Width - this.Size.Width));
                int y = rnd.Next(0, (System.Windows.Forms.SystemInformation.PrimaryMonitorSize.Height - this.Size.Height));
                this.Location = new Point(x, y);
                Thread.Sleep(10);
                touhou += 1;
            }
            imgPeter.Image = Properties.Resources.peter;
        }

有谁知道怎么补救吗?有什么可以试试的吗?我试着把它添加到循环本身,但没有用。

ctzwtxfj

ctzwtxfj1#

//为什么这不起作用?!
但是代码会继续在同一个线程上执行,稍后您会为imgPeter.Image分配一个新值。所有这些都是单线程的阻塞代码,所以当重新绘制表单时,基本上是“最后一个获胜”。类似于:

x = 0;
x = 1;
x = 2;

在这段代码的末尾,x将等于2。它 * 确实 * 等于01,非常简短,但在这些状态下没有做任何事情。
在Windows窗体的上下文中,一种仍然常用的旧方法(无论好坏)是强制窗体重新绘制:

imgPeter.Image = Properties.Resources.retep;
Application.DoEvents(); // <--- here
touhou = 0;
// etc...

不过,说实话这有点像黑客。请记住,在主UI线程上使用Thread.Sleep(10);仍然可能导致意外的UI“故障”。
您可能需要考虑使用asyncawait,用类似await Task.Delay(10);的东西替换Thread.Sleep(10);(在创建整个方法async之后)。async操作的好处是主机应用程序可以继续其正常操作(例如重新绘制屏幕)。
例如:

private async void PictureBox1_Click(object sender, EventArgs e)
{
    imgPeter.Image = Properties.Resources.retep;
    touhou = 0;
    while (touhou < 10)
    {
        int x = rnd.Next(0, (System.Windows.Forms.SystemInformation.PrimaryMonitorSize.Width - this.Size.Width));
        int y = rnd.Next(0, (System.Windows.Forms.SystemInformation.PrimaryMonitorSize.Height - this.Size.Height));
        this.Location = new Point(x, y);
        await Task.Delay(10);
        touhou += 1;
    }
    imgPeter.Image = Properties.Resources.peter;
}

请以后的读者注意:async void的使用用于满足与Windows窗体事件处理程序的向后兼容性。它应该永远被用于这个非常具体的目的之外。使用async Task作为其他需要asyncvoid方法。

相关问题