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;
}