-2

I need to generate two random numbers every X seconds on a WinForms application, but am unable to. My goal is generating two numbers every 2-1 seconds, to show them in the WinForms. The only way my code works is when I put a MessageBox.Show() before generating the two random numbers. Please, explain me the why like I'm five.

What I tried, with my code:

    public partial class FrmPrincipal : Form
    {
        private int temperatura = 0;
        private int umidade = 0;
        public FrmPrincipal()
        {
            InitializeComponent();
        }

        private void cadastrarNovoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FrmCadLote frmCadLote = new FrmCadLote();
            frmCadLote.ShowDialog();
        }

        private void atualizarToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FrmAtualizacaoLote frmAtualizacaoLote = new FrmAtualizacaoLote();
            frmAtualizacaoLote.ShowDialog();
        }

        private void excluirToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FrmExclusaoLote frmExclusaoLote = new FrmExclusaoLote();
            frmExclusaoLote.ShowDialog();
        }

        private void consultarToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FrmConsultaLote frmConsultaLote = new FrmConsultaLote();
            frmConsultaLote.ShowDialog();
        }

        private void btnSensores_Click(object sender, EventArgs e)
        {
            ativaSensor();
        }

        public void ativaSensor()
        {
            Random rnd = new Random();
            Boolean sensorAtivo = false;
            if (!sensorAtivo)
            {
                // It only works when I enable this MessageBox
                MessageBox.Show("ok");
                this.temperatura = rnd.Next(0, 40);
                this.umidade = rnd.Next(0, 100);
                lblUmidade.Text = umidade.ToString();
                lblTemperatura.Text = temperatura.ToString();

                Thread.Sleep(1000);
                ativaSensor();
            }
        }
    }
  • 1
    This issue is referenced specifically in the documentation for the `Random` class, which means that you have asked this question without actually doing your due diligence first. ALWAYS read the relevant documentation. Given that you can open it with a single press of the F1 key, there's no excuse not to. – jmcilhinney Dec 05 '22 at 05:20
  • 2
    Duplicate: [Random number generator only generating one random number](https://stackoverflow.com/questions/767999/random-number-generator-only-generating-one-random-number), but *do* refer to the documentation when you get unexpected results. – Ňɏssa Pøngjǣrdenlarp Dec 05 '22 at 05:23
  • Whilst the comments (and answer) mentioning the misuse of the Random class here are indeed correct observations, that is only half the problem here. Even if they corrected that mistake, they would observe the same problem. The self calling of ativaSensor() means that they are blocking the UI thread. Take a look at the Timer class, and use the OnTick event to generate the new random numbers (and sort out the random class misuse mentioned by others) – Adam G Dec 05 '22 at 05:34
  • @AdamG Thank you, I managed to fix it by using a Timer from the Components tab (VS toolbox), of course, I had to make some adjustments, but it worked. – csharpnewbie Dec 05 '22 at 08:22

1 Answers1

0

As it specifically states in the documentation for the Random class, instances are created using a seed value and that seed defaults to the system time. If you create multiple instances in quick succession, they will likely use the same seed and thus produce the same sequence of pseudo-random numbers.

The whole point of the Random class is that it uses a specific algorithm to produce a sequence of numbers. That means that you're supposed to use one instance repeatedly, so don't create one inside a method that will be called multiple times. Create a single instance and assign it to a field, then use that one instance all the time. If you're targeting .NET 6 or later, you can even use the Random.Shared property to get a singleton instance.

jmcilhinney
  • 50,448
  • 5
  • 26
  • 46
  • In .Net Framework `Environment.TickCount` is used to generate the Seed, while in .NET the [Xoshiro256** algorithm](https://bashtage.github.io/randomgen/bit_generators/xoshiro256.html) is used instead, when no Seed is specified – Jimi Dec 05 '22 at 06:31