0

While I using winforms app, each 5 minute I need to check data updates. I need to send request to few service then get response and update data in database. What's is the best practices to make on another thread (or task ?)? The program should not slow down. I try to make with timer: Init timer when program is running

public class Timer
{

    private System.Timers.Timer timer;
    private void InitTimer()
    {
        timer = new System.Timers.Timer(4000);
        timer.Elapsed += ElapsedTime;
        timer.Enabled = true;
    }

    private void ElapsedTime()
    {
      //send request and update data
    }
}
Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
Rafael
  • 35
  • 5

1 Answers1

0

The way you are doing it will work just fine. The documentation for Sytem.Timers.Timer says:

If the SynchronizingObject property is null, the Elapsed event is raised on a ThreadPool thread.

The SynchronizingObject property is null by default, so your Elasped event will run on a ThreadPool thread, not on the UI thread. That means it will not stop your application from responding to user input.

If there is a chance that ElapsedTime() will run longer than your interval, and you don't want the events overlapping, then you can set AutoReset to false and reset it manually at the end of ElapsedTime(). Just make sure that everything is wrapped in a try/catch block, otherwise the timer won't get reset if there's an exception. My code below shows how that would look.

You don't need to use async/await anywhere here. Since it won't be running on the UI thread, using asynchronous code won't really help you any. In a desktop app, it's not a big deal to have a separate (non-UI) thread wait.

public class Timer
{

    private System.Timers.Timer timer;
    private void InitTimer()
    {
        timer = new System.Timers.Timer(4000);
        timer.Elapsed += ElapsedTime;
        timer.AutoReset = false;
        timer.Enabled = true;
    }

    private void ElapsedTime()
    {
        try {
            //send request and update data
        }
        catch (Exception e)
        {
            //log the error
        }
        finally
        {
            //start the timer again
            timer.Enabled = true;
        }
    }
}
Gabriel Luci
  • 38,328
  • 4
  • 55
  • 84
  • "*In a desktop app, it's not a big deal to have a separate (non-UI) thread wait.*" -- Although this is true, using async/await increases the `ThreadPool` availability, and comes at no tangible cost at performance or convenience (assuming that the programmer is already familiar with the technology), so I wouldn't agree with the advice to avoid it. – Theodor Zoulias Dec 17 '21 at 22:57
  • @TheodorZoulias Normally I'd agree, but using async inside an event handler is tricky since it's `void`. You still *could* make it async, but it makes things a bit more complicated and I just don't think it's worth it. But to each their own. – Gabriel Luci Dec 17 '21 at 23:32
  • Gabriel AFAIK the purpose of [async void](https://docs.microsoft.com/en-us/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming#avoid-async-void) is specifically to make asynchronous event handlers possible. So using it for its intended purpose should be OK. A consequence of using `async` in the `Elapsed` handler might be (I haven't tested it) that any unhandled exception will propagate, instead of been swallowed, which is the ["subject to change"](https://docs.microsoft.com/en-us/dotnet/api/system.timers.timer.elapsed#remarks) behavior of this tricky event. – Theodor Zoulias Dec 18 '21 at 00:12
  • 1
    @TheodorZoulias Agreed. You could do it either way. – Gabriel Luci Dec 18 '21 at 01:37