TTurb
TTurb

Reputation: 13

C# backgroundworker loop change label text

I have a Label in my form and want to change its text every second. I thought that a BackgroundWorker is what I need but the while loop in it doesn't seem to work. The first line in the loop does its job but after a Thread.Sleep the loop seems to stop.

public MainForm()
{           

    InitializeComponent();

    backgroundWorker1.DoWork += new DoWorkEventHandler(getFrame);

    backgroundWorker1.RunWorkerAsync();
}

void getFrame(object sender, DoWorkEventArgs e)
{
    while(true) {
        ageLabel.Text = "test";
        Thread.Sleep(1000);
        ageLabel.Text = "baa";
        Thread.Sleep(1000);
    }
}

Upvotes: 1

Views: 1240

Answers (2)

Mong Zhu
Mong Zhu

Reputation: 23732

The stopping occurs because you run into a System.InvalidOperationException exception which occurs because you try to manipulate a control element from a different thread than it was created on.

To solve your problem you can use Control.BeginInvoke. This method will pull the execution of the control manipulation on the main thread:

while (true)
{
    ageLabel.BeginInvoke(new Action(() => { ageLabel.Text = "test"; }));
    Thread.Sleep(1000);
    ageLabel.BeginInvoke(new Action(() => { ageLabel.Text = "bla"; }));
    Thread.Sleep(1000);
}

If working with windows forms in visual studio it is adviseable to look into the output window. Exceptions such as this one will be shown there. :)

EDIT: if you simply want to update the UI component property on a timed intervals, you could as well use a Timer, which was built for this exact purpose. It is executed on the main UI thread and thus does not need any invocation.

But in general the idea still holds, if you want to manipulate a control from a different thread than it was created on, then you need invocation!

Upvotes: 2

DonBoitnott
DonBoitnott

Reputation: 11025

Instead, use a Timer. Consider this example, where label1 is a simple Label control on a WinForm:

public partial class Form1 : Form
{
    Timer _timer = new Timer();

    public Form1()
    {
        InitializeComponent();

        _timer.Interval = 1000;
        _timer.Tick += _timer_Tick;
        _timer.Start();
    }

    private void _timer_Tick(Object sender, EventArgs e)
    {
        label1.Text = DateTime.Now.ToString();
    }
}

Upvotes: 2

Related Questions