1

Suppose I need to draw pixel by pixel with some delay so that the points are displayed one by one. I wrote the following code:

            for (int i = 0; i < 300; ++i)
        {
            Random random = new Random();
            Point point = new Point(random.Next(0, bmp.Width), random.Next(0, bmp.Height));
            bmp.SetPixel(point.X, point.Y, Color.Black);
            pictureBox1.Image = bmp;
            Thread.Sleep(10);
        }

But it doesn't work! The program freezes until 300 points are set on the bitmap, and then displays them all at the same time on the pictureBox

What am I doing wrong ? I didn't find anything about that.

I would be grateful for any advice, why this is happening and how to fix it. Sorry for my bad english.

vosure
  • 25
  • 4
  • Speed in obviously not of concern here. Lockbits has nothing to do with it. The UI updates only happen when there is time. The only thing missing was a Refresh to enforce the update.. – TaW Dec 15 '18 at 14:16
  • As a matter of principle you should use only one and the same Random object, not always create new ones. – TaW Dec 15 '18 at 14:18

1 Answers1

0

I managed to make a working solution for you:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private Bitmap bmp = new Bitmap(100,100);

    private void Form1_Load(object sender, EventArgs e)
    {
        pictureBox1.Image = bmp; //only assign it once!
    }

    private async void button1_Click(object sender, EventArgs e)
    { // method that starts the picturebox filling. You can declare it anywhere else.
        for (int i = 0; i < 300; ++i)
        {
            Random random = new Random();
            Point point = new Point(random.Next(0, bmp.Width), random.Next(0, bmp.Height));
            bmp.SetPixel(point.X, point.Y, Color.Black); //we are updating the reference of 'bmp', which the pictureBox already contains
            pictureBox1.Refresh(); //force the picturebox to redraw its bitmap
            await Task.Delay(100); // async delay, to prevent the UI from locking
        }
    }
}
garry man
  • 445
  • 4
  • 14
  • Because of `Thread.Sleep`. You should avoid using it if you're not working with separate `Threads`. Always use TPL `Task` for doing multithreading, if you can. Also check this out https://stackoverflow.com/questions/20082221/when-to-use-task-delay-when-to-use-thread-sleep – garry man Dec 15 '18 at 14:13
  • PS> Other changes I've made to your code are for performance reasons. – garry man Dec 15 '18 at 14:18