Ah I see. I was confused by the wording “like monogame does on the client side.”
Timers can be more convenient because you have an encapsulated object that’s counting on its own, with the ability to easily start and stop them. Usage is nice because when the timer completes, it will call your event function that has been preconfigured, so you don’t constantly need to check if it’s done.
If you need complex timers that don’t work with that standard behavior, then you can run your own in the game loop. But any standard timer (e.g. saving a completion time, comparing the current time to see if it’s done, calling a function) is basically recreating that small amount of logic that’s already done for you. Of course if you use a ton of timers, this might be preferable for garbage reasons.
Another cool thing to try if you need some customization is
Task.Delay. It uses a timer internally (see the source), but instead of configuring the event function at the start, you can pass around your task and let different services check
IsCompleted within their update loops.