Reputation: 8472
What am I doing wrong here?
my plan is to change the label text property from a different thread without getting the "Cross-thread operation not valid" exception.
private void button1_Click(object sender, EventArgs e)
{
Thread thread1 = new Thread(new ThreadStart(ChangeTime));
thread1.Start();
}
delegate void SetTimeDelegate();
private void ChangeTime()
{
while (true)
{
if (lbl1.InvokeRequired)
{
SetTimeDelegate setTime = new SetTimeDelegate(ChangeTime);
lbl1.Invoke(setTime);
}
else
{
lbl1.Text = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss tt");
Thread.Sleep(1000);
}
}
}
Upvotes: 0
Views: 3699
Reputation: 299
To update a UI control from a different thread you need to call the BeginInvoke
or Invoke
method. You can use the specific control's methods or the form's.
Your original code has infinite recursion. You are Invoking correctly except your delegate is calling the same method. Create a separate method for updating the label with the time and have the delegate cll that new method.
private bool _IsShuttingDown = false;
private void ChangeTime()
{
while (!_IsShuttingDown)
{
if (lbl1.InvokeRequired)
{
SetTimeDelegate setTime = new SetTimeDelegate(UpdateTimeLabel);
lbl1.Invoke(setTime);
Thread.Sleep(1000);
}
else
{
UpdateTimeLabel();
Thread.Sleep(1000);
}
}
}
private void UpdateTimeLabel()
{
lbl1.Text = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss tt");
}
protected override void OnClosing(CancelEventArgs e)
{
_IsShuttingDown = true;
base.OnClosing(e);
}
I also added a field on the form to exit the loop when the form is closing or else weird things happen.
My original code:
if (lbl1.InvokeRequired)
{
lbl1.Invoke((Action)(() => lbl1.Text = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss tt")));
Thread.Sleep(1000);
}
Upvotes: 3