2015-07-28 2 views
2

По какой-то причине этот замораживает программу:C# Анимация замораживает программу

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

почему?
pictureBox2 содержит первый кадр и pictureBox3 содержит второй.
pictureBox1 содержит «анимацию». (Как показано в коде)

EDIT: Я не хочу, чтобы анимировать РАЗ, я хочу, чтобы анимировать НАВСЕГДА.

ответ

2

Вот один из способов ...

Марка ваше Показанное() события с async, а затем использовать await 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 
     } 
    } 

---------- Редактировать --- -------

Альтернативный подход с использованием таймера и IEnumerator.Это было бы хорошим способом, если бы у вас было больше двух фреймов:

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

YAY! в конце концов... –

0

Создать параллельный поток для вашего animiation:

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())); 
    } 
} 
1

В вашем случае, значение x всегда 1, и именно поэтому цикл в то время как держать итерацию, и программа переходит в бесконечном цикле.

Решение:

Вы должны использовать BackgroundWorker для запуска кода в качестве Asynchronous

Вставьте новый 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(); 
+0

ОП сказал, что анимация должна продолжаться. 'if' остановит его, просто изменив 2 кадра. – Shaharyar

+0

@VishalSuthar, я думаю, OP хочет, чтобы цикл работал вечно, поэтому я думаю, что ваш ответ не поможет. Ему нужно разблокировать поток, чтобы иметь возможность запускать фоновые задачи, которые позволяют обновлять изображения, которые будут отображаться. –

0

Ваша петля работает вечно и никогда не заканчивается.

Не существует условия прекращения для цикла 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 
    } 
} 

DoEvents() только один вариант, может быть, не самое лучшее для вашего дела. Вам, вероятно, лучше написать правильный таймер, который переключается между двумя изображениями за 40 миллисекунд или независимо от скорости вашей анимации.

+0

да ладно. что не помогает мне –

+0

Ваш цикл 'while (x <2)' работает вечно. Не существует условия терминации, поэтому ваша программа зависает. 'x' всегда меньше 2. –

+0

я знаю. Sheesh! –

0

Я думаю, вы должны добавить некоторые задержки времени между frame1 и frame2 внутри цикла while, чтобы увидеть работу анимации.

+0

Он по-прежнему будет блокировать пользовательский интерфейс, потому что он работает в потоке пользовательского интерфейса. – Shaharyar

Смежные вопросы