Reputation:
I am building cross platform apps with Xamarin and MvvmCross. I need to call the server to the updates every minute (I will move to push notifications later) but I am unable to make a timer in my Core Project. I've seen MvvmCross N+42 but I believe the target projects are older which allows the timer. Below is my target framework.
Is there a better way for me to constantly call a method which calls a service?
Upvotes: 10
Views: 3242
Reputation: 6375
@stevemorgan answer works really well. I created a Timer utility based on that code to make it more reusable. I also added a "runOnce" parameter that will stop the timer after the first tick
public class PclTimer
{
public bool IsRunning { get; private set; }
public TimeSpan Interval { get; set; }
public Action Tick { get; set; }
public bool RunOnce { get; set; }
public Action Stopped { get; set; }
public Action Started { get; set; }
public PclTimer(TimeSpan interval, Action tick = null, bool runOnce = false)
{
Interval = interval;
Tick = tick;
RunOnce = runOnce;
}
public PclTimer Start()
{
if (!IsRunning)
{
IsRunning = true;
Started?.Invoke();
var t = RunTimer();
}
return this;
}
public void Stop()
{
IsRunning = false;
Stopped?.Invoke();
}
private async Task RunTimer()
{
while (IsRunning)
{
await Task.Delay(Interval);
if (IsRunning)
{
Tick?.Invoke();
if (RunOnce)
{
Stop();
}
}
}
}
}
I´m using this in MvvmCross with no issues:
timer = new Timer(TimeSpan.FromSeconds(4),
() => ShowViewModel<UserMatchViewModel>(), true)
.Start();
Upvotes: 9
Reputation: 13091
You can always do it yourself thanks to the wonder of async/await:
public async Task RunTimer()
{
while(_timerRunning)
{
// Do Work
// ...
await Task.Delay(_timerInterval);
}
}
When you call it, don't await it. It will run on a background thread and you can terminate the loop by setting the _timerRunning field from elsewhere (or by killing the Task that's returned from the call).
Upvotes: 3