Search code examples
c#.net-4.0timerbackgroundworkerwindows

How Change A Label's Text In A Timer's Tick (GUI Is Busy)


i have a strange situation.
please see the backgroundWorker5_RunWorkerCompleted event:

    private void backgroundWorker5_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        btnStartAdventures.Text = "Start Adventure";
        btnStartAdventures.Enabled = true;

        if (e.Error != null)
        {
            MessageBox.Show(e.Error.Message);
            return;
        }
        if (e.Cancelled)
        {
            lblStatusValueInAdventures.Text = "Cancelled...";
        }
        else
        {
            lblStatusValueInAdventures.Text = "Completed";
            timer1.Enabled = true;
            timer1.Start();
            // MessageBox.Show("start timer");
            Thread.Sleep((int.Parse(txtDelayInAdventures.Text)) * 60000);
            //MessageBox.Show("end timer");
            timer1.Enabled = false;
            timer1.Stop();
            lblTimer.Text = "0";
            btnStartAdventures.PerformClick();
        }
    }

and that Timer is :

private void timer1_Tick(object sender, EventArgs e)
{
    this.Invoke(new MethodInvoker(delegate { lblTimer.Text = (int.Parse(lblTimer.Text) + 1).ToString(); }));
}

but this timer can not change lblTimer's Text.
how can i fix this problem?

EDIT:
that Thread.Sleep is necessary and i can not remove it.
i want a loop that never ends and those codes are for that.

thanks in advance


Solution

  • As requested;

    What do you mean by "a loop that never ends"? A Thread.Sleep on the UI thread (RunWorkerCompleted event executes on the UI thread) will effectively freeze the UI thread, which means that no interaction with the UI thread will be shown.

    Comments:

    What are you trying to achieve? As far as I can guess, you are doing some work in a background thread - backgroundWorker5 - (the UI thread is responsive). When backgroundWorker5 is finished you want to start a timer and display a counter in a label while the UI is still responsive (for somebody to stop the timer maybe?). Something like that? – Mario 3 mins ago edit

    yes you are right. i want a loop and it never stops until a user click cancel button. – MoonLight 1 min ago

    So, try something like this:

    int time = 0;
    
    private void backgroundWorker5_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        btnStartAdventures.Text = "Start Adventure";
        btnStartAdventures.Enabled = true;
    
        if (e.Error != null)
        {
            MessageBox.Show(e.Error.Message);
            return;
        }
        if (e.Cancelled)
        {
            lblStatusValueInAdventures.Text = "Cancelled...";
        }
        else
        {
            lblStatusValueInAdventures.Text = "Completed";
            timer1.Interval = 1000; //<--- Tick each second, you can change this.
            timer1.Enabled = true;
            timer1.Start();
            // MessageBox.Show("start timer");
        }
    }
    
    private void timer1_Tick(object sender, EventArgs e)
    {
        lblTimer.Text = (time + 1).ToString();
    }
    
    private void button_Cancel_Click(object sender, EventArgs e)
    {
        //MessageBox.Show("end timer");
        timer1.Enabled = false;
        timer1.Stop();
        lblTimer.Text = "0";
        btnStartAdventures.PerformClick();
    }