Is it possible (or even reasonable) to make the callback of a System.Timers.Timer
an async method? Something like:
var timer = new System.Timers.Timer
{
Interval = TimeSpan.FromSeconds(30).TotalMilliseconds,
AutoReset = true
};
timer.Elapsed += async (sender, e) => { /* await something */ };
timer.Start();
It compiles (obviously a good place to start), but I'm not sure I understand the consequences. Will the timer await
the callback before resetting the timer?
Elapsed time is the amount of time that passes from the start of an event to its finish. In simplest terms, elapsed time is how much time goes by from one time (say 3:35pm) to another (6:20pm).
Yes, they run in a different thread.
It would have already queued before you have called Stop method. It will fire at the elapsed time. To avoid this happening set Timer. AutoReset to false and start the timer back in the elapsed handler if you need one.
Elapsed event every two seconds (2000 milliseconds), sets up an event handler for the event, and starts the timer. The event handler displays the value of the ElapsedEventArgs. SignalTime property each time it is raised.
Will the timer
await
the callback before resetting the timer?
No. There's nothing it could await, because the signature of ElapsedEventHandler
has a void return type.
In other words, your code is equivalent to:
var timer = new System.Timers.Timer { ... };
timer.Elapsed += Foo;
timer.Start();
...
private async void Foo()
{
...
}
Whether that's acceptable for you or not will depend on your context. In general, having async void methods or anonymous functions makes them harder to test and reuse - but the ability was precisely given for the sake of event handlers... You should consider how errors will be propagated though.
The title of the question is specifically about Timers, but if we look at it as "How to call an async method after some time?" then you could do it without using a timer.
var task2 = Task.Run(async () => {
while (true)
{
try
{
await MyMethod2();
} catch
{
//super easy error handling
}
await Task.Delay(TimeSpan.FromSeconds(5));
}
});
...
public async Task MyMethod2()
{
//async work here
}
Please note however that this will have different timing (timer will be called at an interval, the code above will be called every (run time + sleep_time), but even if MyMethod2
takes a long time it it won't be called twice. Having said that, you can calculate how long to await for to run 'every x minutes'.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With