C#动画冻结程序

C#动画冻结程序,c#,winforms,animation,C#,Winforms,Animation,出于某种原因,这会冻结程序: private void Form1_Shown(object sender, EventArgs e) { int x = 1; var frame1 = pictureBox2.BackgroundImage; var frame2 = pictureBox3.BackgroundImage; while(x < 2) { pictureBox1.BackgroundImage = frame1;

出于某种原因,这会冻结程序:

private void Form1_Shown(object sender, EventArgs e)
{
    int x = 1;
    var frame1 = pictureBox2.BackgroundImage;
    var frame2 = pictureBox3.BackgroundImage;
    while(x < 2)
    {
        pictureBox1.BackgroundImage = frame1;
        pictureBox1.BackgroundImage = frame2;
    }
}
private void Form1\u显示(对象发送方,事件参数e)
{
int x=1;
var frame1=pictureBox2.BackgroundImage;
var frame2=pictureBox3.BackgroundImage;
而(x<2)
{
pictureBox1.BackgroundImage=frame1;
pictureBox1.BackgroundImage=frame2;
}
}
为什么?
pictureBox2
包含第一帧,
pictureBox3
包含第二帧。
pictureBox1
包含“动画”。(如代码中所示)


编辑:我不希望它一次设置动画,我希望它永远设置动画。

为动画创建平行线程:

private void Form1_Shown(object sender, EventArgs e)
{
    //create parallel thread
    Thread animationThread = new Thread(Animation);
    animationThread.Start();
}

//create a new method for animation to run on a parallel thread
private void Animation()
{
    int x = 1;
    var frame1 = pictureBox1.Image;
    var frame2 = pictureBox2.Image;
    while (x < 2)
    {
        this.Invoke(new Action(() => pictureBox3.Image = frame1));
        this.Invoke(new Action(() => pictureBox3.Refresh()));
        Thread.Sleep(100); //you must keep a dealy other wise it will consume too much processing
        this.Invoke(new Action(() =>  pictureBox3.Image = frame2));
        this.Invoke(new Action(() => pictureBox3.Refresh()));
    }
}
private void Form1\u显示(对象发送方,事件参数e)
{
//创建平行线程
线程动画线程=新线程(动画);
animationThread.Start();
}
//为动画创建新方法以在并行线程上运行
私有void动画()
{
int x=1;
var frame1=pictureBox1.Image;
var frame2=pictureBox2.Image;
而(x<2)
{
调用(新操作(()=>pictureBox3.Image=frame1));
调用(新操作(()=>pictureBox3.Refresh());
Thread.Sleep(100);//您必须严格遵守其他规定,否则会占用太多的处理时间
调用(新操作(()=>pictureBox3.Image=frame2));
调用(新操作(()=>pictureBox3.Refresh());
}
}
在您的例子中,
x
的值总是
1
,这就是为什么while循环不断迭代,程序进入无限循环的原因

解决方案:

您应该使用以异步方式运行代码

在表单中插入新的
BackgroundWorker

将函数插入
DoWork
事件

private void bWorker1_DoWork(object sender, DoWorkEventArgs e)  
{  
    var frame1;
    var frame2;

    if (pictureBox2.InvokeRequired) { pictureBox2.Invoke((MethodInvoker)delegate { frame1 = pictureBox2.BackgroundImage; }); } else { frame1 = pictureBox2.BackgroundImage; }
    if (pictureBox3.InvokeRequired) { pictureBox3.Invoke((MethodInvoker)delegate { frame2 = pictureBox3.BackgroundImage; }); } else { frame2 = pictureBox3.BackgroundImage; }

    while (true)
    {
        if (pictureBox1.InvokeRequired) { pictureBox1.Invoke((MethodInvoker)delegate { pictureBox1.BackgroundImage = frame1; }); } else { pictureBox1.BackgroundImage = frame1; }
        if (pictureBox1.InvokeRequired) { pictureBox1.Invoke((MethodInvoker)delegate { pictureBox1.BackgroundImage = frame2; }); } else { pictureBox1.BackgroundImage = frame2; }
    }
}
现在,开始运行
BackgroundWorker

bWorker1.RunWorkerAsync();

您的循环将永远运行,永不终止

while(x<2)循环没有终止子句,因此程序冻结<代码>x始终小于2。如果不允许应用程序呼吸,它将冻结。试试这个:

private void Form1_Shown(object sender, EventArgs e)
{
    var frame1 = pictureBox2.BackgroundImage;
    var frame2 = pictureBox3.BackgroundImage;
    while(true)
    {
        pictureBox1.BackgroundImage = frame1;
        Application.DoEvents(); // give the thread room to run background tasks

        pictureBox1.BackgroundImage = frame2;
        Application.DoEvents(); // give the thread room to run background tasks
    }
}

()只是一种选择,也许对你来说不是最好的。你最好写一个合适的计时器,每隔40毫秒在两个图像之间切换一次,或者不管你的动画速度是多少。

我认为你应该在while循环中的frame1和frame2之间添加一些时间延迟,以查看动画效果。

这里有一种方法

使用
async
标记所显示的()事件,然后在帧之间使用
wait Task.Delay()

    private async void Form1_Shown(object sender, EventArgs e)
    {
        bool first = true;
        var frame1 = pictureBox2.BackgroundImage;
        var frame2 = pictureBox3.BackgroundImage;
        while (true)
        {
            pictureBox1.BackgroundImage = first ? frame1 : frame2;
            first = !first;
            await Task.Delay(500); // 1/2 second delay <-- set it to your desired delay between frames
        }
    }
private async void Form1\u显示(对象发送方,事件参数e)
{
bool first=true;
var frame1=pictureBox2.BackgroundImage;
var frame2=pictureBox3.BackgroundImage;
while(true)
{
pictureBox1.BackgroundImage=第一帧?第1帧:第2帧;
第一个=!第一个;

等待任务。延迟(500);//1/2秒延迟是的,好的。这对我没有帮助。你的循环
,而(x<2)
永远运行。没有终止子句,因此你的程序冻结。
x
总是小于2。这不是答案。因为它不能解决问题,OP问“为什么?”-不是“如何解决问题?”请参阅更新的答案;-)OP说动画必须继续运行。
如果只更改了2帧,就会停止。@VishalSuthar,我想OP希望循环永远运行,所以我想你的答案不会有多大帮助。他需要解锁线程才能运行后台任务,以便刷新要渲染的图片。它将我仍然阻止UI,因为它在UI线程上运行。
    private IEnumerator<Image> frames;
    private System.Windows.Forms.Timer tmr;

    private void Form1_Shown(object sender, EventArgs e)
    {
        List<Image> lstFrames = new List<Image>();
        lstFrames.Add(pictureBox2.BackgroundImage);
        lstFrames.Add(pictureBox3.BackgroundImage);
        lstFrames.Add(pictureBox4.BackgroundImage);
        // etc...
        frames = lstFrames.GetEnumerator();
        DisplayNextFrame();

        tmr = new System.Windows.Forms.Timer();
        tmr.Interval = 500;
        tmr.Tick += Tmr_Tick;
        tmr.Start();
    }

    private void Tmr_Tick(object sender, EventArgs e)
    {
        DisplayNextFrame();
    }

    private void DisplayNextFrame()
    {
        if (!frames.MoveNext())
        {
            frames.Reset();
            frames.MoveNext();
        }
        pictureBox1.BackgroundImage = frames.Current;
    }