Gewoo
Gewoo

Reputation: 109

Show random pictures in picture box C#

I have 6 images called image_1, image_2... Now I want to show these pictures in random order in a picture box so I created this code:

for (int i = 0; i < 10; i++)
{
    diceBox.ImageLocation = "images/dice_" + rn.Next(1,6).ToString() + ".png";
    diceBox.Update();
    Task.Delay(1000);
}

But this does not work. It only shows 1 of the pictures. I have a feeling it is skipping the "Task.Delay(1000)", how can I fix this?

Upvotes: 1

Views: 835

Answers (1)

Enigmativity
Enigmativity

Reputation: 117055

The issue with the code is not the Task.Delay(1000);. That's basically instantly creating a task whose result is never looked at, but the code that calls it is instantly moving on. It's not waiting for the task to complete. It's effectively a no-op in this code.

The issue is that, even with the diceBox.Update(), the UI doesn't get a chance to actually redraw the control. The for loop is keeping the UI from doing any redraws. So the final image that is selected in the for loop is the only one displayed because it is only after the loop that the UI can update.

The trick is to use some sort of timer to update control. My favoured choice is using Microsoft's Reactive Extensions (NuGet "Rx-WinForms"). Here's what the code would look like:

Observable
    .Interval(TimeSpan.FromSeconds(1.0))
    .Take(10)
    .ObserveOn(diceBox)
    .Subscribe(fn =>
    {
        diceBox.ImageLocation = String.Format("images/dice_{0}.png", rn.Next(1, 7));
        diceBox.Update();
    });

A more standard timer approach would be to do this:

var i = 0;
var timer = new System.Windows.Forms.Timer();
EventHandler handler = null;
handler = (s2, e2) =>
{
    diceBox.ImageLocation = String.Format("images/dice_{0}.png", rn.Next(1, 7));
    diceBox.Update();
    if (++i >= 10)
    {
        timer.Enabled = false;
        timer.Tick -= handler;
        timer.Dispose();
    }
};
timer.Tick += handler;
timer.Interval = 1000;
timer.Enabled = true;

I like the Reactive Extensions approach - it reads nicely from top to bottom. The standard timer approach jumps all over the place, but might be more familiar.

I have tested both approaches and they appear to work fine.

Upvotes: 2

Related Questions