Reputation: 273
I'm trying to display an error on my form and use timer to remove the error in a second. I have:
const string sendingError = "currently sending a message please wait";
System.Timers.Timer timer = new System.Timers.Timer(1000);
commandValues.errorList[sendingError] = sendingError;
commandValues.updateErrorList();
this functions as it should by updating a label with the error message
timer.Elapsed += ((source, e) =>
{
var INDEX = Form.ActiveForm.Controls.IndexOfKey("errorBox");
Debug.WriteLine(Form.ActiveForm.Controls[INDEX]);
Form.ActiveForm.Controls[INDEX].Text = "";
Debug.WriteLine("2" + Form.ActiveForm.Controls[INDEX]);
});
timer.Enabled = true;
timer.Start();
the debug line displays
1System.Windows.Forms.Label, Text: currently sending a message please wait
1System.Windows.Forms.Label, Text: currently sending a message please wait
1System.Windows.Forms.Label, Text: currently sending a message please wait
1System.Windows.Forms.Label, Text: currently sending a message please wait
// etcetera
As you can see, the second debug line is never displaying. Break points agree that it leaves the delegate when I try to change the label.
I'm new to C# so any advice would be appreciated, but specifically I would like to know how to have the main form edited after a timeout and why my attempt is failing.
Upvotes: 0
Views: 2698
Reputation: 925
I'm not positive I understand your problem, but it sounds like you're having an issue updating the UI from a background thread? If so, try this:
timer.Start() starts a new thread separate from your Winform's UI thread, so you may need to Invoke your WinForm's thread in order to see the changes.
timer.Elapsed += ((source, e) =>
{
var INDEX = Form.ActiveForm.Controls.IndexOfKey("errorBox");
Debug.WriteLine(Form.ActiveForm.Controls[INDEX]);
//Invoke the instance of "Form" to process changes on the UI thread
Form.Invoke((MethodInvoker)delegate
{
Form.ActiveForm.Controls[INDEX].Text = "";
});
Debug.WriteLine("2" + Form.ActiveForm.Controls[INDEX]);
});
timer.Enabled = true;
timer.Start();
If WinForm and NOT Data Bound
myControl.Invoke((MethodInvoker) delegate {/*update UI related values here*/});
or
myForm.Invoke((MethodInvoker) delegate {/*update UI related values here*/});
If WinForm and Data Bound, you may need to update the UI by updating the databound property of your object, or invoke the databound object to update its own property (queueing INotifyPropertyChange or another similar Interface which will force refresh the UI). Note that refactoring your code to data-bind objects to your UI could also prove a permanent solution.
If XAML\WPF, you can use the following snippet to force update your XPF\XAML UI from the base application's dispatcher, like this:
System.Windows.Application.Current.Dispatcher.Invoke((System.Action)delegate {/*update UI related values here*/});
Cheers!
Upvotes: 3
Reputation: 8500
You should dispatch UI modifications from your Timer thread
to UI Thread
. Modifying UI elements from another threads is not allowed.
To do it you need to call this.BeginInvoke
.
How to update the GUI from another thread in C#?
Upvotes: 0