I am trying to have a system.timer calculate a object and return it to the calling tread in C#. If I calculate it the main trad then i get the object, but if I try to calculate the same in a system.timer I do not get any value back.
How to return a object from a system.timer an use it in the main tread?
public MainWindow()
{
Timer execute = new Timer();
execute.Interval = 5000;
execute.Elapsed += UpdatePending;
execute.Start();
InitializeComponent();
}
private void UpdatePending(Object source, System.Timers.ElapsedEventArgs e)
{
DataTable pending = new Repository().GetPending();
if (pending?.Rows.Count > 0)
{
dataGrid_Pending.DataContext = pending;
}
}
The dataGrid_Pending is not updating when I do this, but it is if I run the code in the main tread:
DataTable pending = new Repository().GetPending();
if (pending?.Rows.Count > 0)
{
dataGrid_Pending.DataContext = pending;
}
You need to politely ask the UI thread to run some code on your behalf. There are many ways to do this
Some of these require you to save an object to use in your timer event. If you are using WPF the dispatcher is probably easiest to use, since you can use the static
Application.Current.Dispatcherto get it:Note that whenever you are dealing with multiple threads, and timers.timer will by default invoke the event handler on a thread pool thread, you cannot access the UI, and you have to ensure the code is thread safe.
You might consider using a
DispatcherTimerinstead, since this will invoke events on the UI thread, removing the problem. This is the best approach if your event handler is fairly fast, say ~50ms or so.If it is slower it might be more useful to run the event on a background thread, but then you need to worry about what will happen if one event handler does not finish before the next tick occur, in addition to any thread safety concerns.