C# -> Android (Xamarin) -> start task every 5 minutes in Background - c#

i want to run a task every 5 minutes. i've tried to solve it with an IntentService and AlarmManager, my code:
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
var tkrServiceIntent = new Intent(this, typeof(GpsDataHandler));
var tkrServicePendingIntent = PendingIntent.GetService(this, 0, tkrServiceIntent, 0);
long interval = 5000;
var firstStart = (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) + 1000;
var am = (AlarmManager)GetSystemService(Context.AlarmService);
am.SetInexactRepeating(AlarmType.RtcWakeup, firstStart, interval, tkrServicePendingIntent);
Toast.MakeText(this, "Service started", ToastLength.Long).Show();
}
i receive the toast, that the service is started, but if i look in running services, there is no service for my application. Can you tell me where the problem ist?

IntentService in an "activity" (if we can call it) runing in Background of the app, so finnally it will call the OnDestroy() ..
You can use the timer to fix your problem , like :
using System;
using System.Threading;
class TimerExampleState {
public int counter = 0;
public Timer tmr;
}
class App {
public static void Main() {
TimerExampleState s = new TimerExampleState();
// Create the delegate that invokes methods for the timer.
TimerCallback timerDelegate = new TimerCallback(CheckStatus);
// Create a timer that waits one second, then invokes every second.
Timer timer = new Timer(timerDelegate, s, 1000, 1000);
// Keep a handle to the timer, so it can be disposed.
s.tmr = timer;
// The main thread does nothing until the timer is disposed.
while (s.tmr != null)
Thread.Sleep(0);
Console.WriteLine("Timer example done.");
}
// The following method is called by the timer's delegate.
static void CheckStatus(Object state) {
TimerExampleState s = (TimerExampleState) state;
s.counter++;
Console.WriteLine("{0} Checking Status {1}.",DateTime.Now.TimeOfDay, s.counter);
if (s.counter == 5) {
// Shorten the period. Wait 10 seconds to restart the timer.
(s.tmr).Change(10000,100);
Console.WriteLine("changed...");
}
if (s.counter == 10) {
Console.WriteLine("disposing of timer...");
s.tmr.Dispose();
s.tmr = null;
}
}
}
Source : https://developer.xamarin.com/api/type/System.Threading.Timer/

Hope this code helps you:-
async void StartTimer()
{
await Task.Delay(60000); //60 seconds
// Do your code
StartTimer(); // Again Call
}
Call "StartTimer()" method where you want to. Call only once time then it calls automatically after 60 seconds.
Thanks !!!

you can create your own timer using xamarin forms device class
sample timer class:
public class Timer {
public Timer(int interval)
{
_interval = TimeSpan.FromMilliseconds(interval);
}
private bool _isRunning;
private readonly TimeSpan _interval;
private Action Tick;
public void Start(Action tick)
{
_isRunning = true;
Tick = tick;
Xamarin.Forms.Device.StartTimer(_interval,() =>
{
Tick?.Invoke();
return _isRunning;
});
}
public void Stop()
{
_isRunning = false;
Tick = null;
}
}

Create a service class. Call DoWork method in OnStartCommand method. Check whether the log is getting printed after every 5 seconds.
public void DoWork()
{
var t = new Thread(() =>
{
while (true)
{
Log.Debug("Service", "Service running");
Thread.Sleep(5000);
}
});
t.Start();
}

Related

Safe to dispose of System.Threading.Timer in timer callback? [duplicate]

I'm using Threading.Timer, like:
new Timer(new TimerCallback(y=>
{
try
{
Save(Read(DateTime.Now));
// here i want to dispose this timer
}
catch
{
}
}),null,100000,10000);
How can I dispose this timer inside of a callback. or workaround?
Update: Let me explain the situation. I want to try to call the method "Save", while it throws an exception. If it works, I need to stop the timer.
Try this:
Timer timer = null;
timer = new Timer(new TimerCallback(y =>
{
try
{
Save(Read(DateTime.Now));
// here i want to dispose this timer
timer.Dispose();
}
catch
{
}
}));
timer.Change(10000, 10000);
EDIT:
I changed the above code slightly according to Chuu's suggestion. Note that if the TimerCallback is called simultanuously by different timer events, Timer.Dispose may end up being called several times. Luckily the Timer does not care if it is being disposed of several times.
Here's a better way to do this. When you use the constructor with only one param (TimerCallback), the state passed to the callback will be the timer itself.
Timer timer = new Timer(o =>
{
((Timer)o).Dispose();
//Your code here
});
//Start the timer
timer.Change(100000,10000);
Here is an example from the msdn docs :
public void StartTimer(int dueTime)
{
Timer t = new Timer(new TimerCallback(TimerProc));
t.Change(dueTime, 0);
}
private void TimerProc(object state)
{
// The state object is the Timer object.
Timer t = (Timer) state;
t.Dispose();
Console.WriteLine("The timer callback executes.");
}
http://msdn.microsoft.com/en-us/library/ms149618(v=vs.110).aspx
You need to keep the reference of the timer in a variable -
public class MyClass
{
private Timer _timer;
public void StartTimer()
{
_timer = new Timer(new TimerCallback(y=>{
try
{
Save(Read(DateTime.Now));
_timer.Dispose();
}
catch {
}
}),null,100000,10000);
}
}
Note: This is untested code. Please check if it works and update.
You'll have to store a reference to the timer somewhere and pass that in as state to the timer object itself. Try creating a class something like this:
public class TimerContainer
{
public Timer Timer { get; set; }
}
Then use it in your method like so:
Action<object> tcb = state =>
{
var container = (TimerConatiner)state;
try
{
Save(Read(DateTime.Now));
container.Timer.Dispose();
}
catch
{
// whatever...
}
};
var container = new TimerContainer();
container.Timer = new Timer(tcb, container, 100000, 10000);
Take care if you use multithreading or multitasking! if so, here you're the code and a solucion for a CancelAfter method extensor (.net 4.0):
private static object syncObj = new object();
public static void CancelAfter(this CancellationTokenSource source, int timeoutMilliseconds, Action code = null)
{
if (timeoutMilliseconds == 0) return; // No timeout
if (source == null)
{
throw new NullReferenceException();
}
if (timeoutMilliseconds < -1)
{
throw new ArgumentOutOfRangeException("timeout");
}
Timer timer = new Timer(delegate(object self)
{
lock (syncObj)
{
try
{
if (null != code)
code.Invoke();
source.Cancel();
((IDisposable)self).Dispose();
}
catch (ObjectDisposedException)
{
}
}
});
timer.Change(timeoutMilliseconds, -1);
}
}
Regards,
Juanlu, ElGuerre

System.Timers.Timer Stop losing values?

I am making a console application that will later be a Windows service application through Topshelf.
I am struggling with timers, I setup a timer with autoreset of 20 seconds. When I start the timer it works. And when I stop it it stops.
Now to the problem, I want to keep the value when stopping it.
I need an event handler as Timer offers. But I also need to have a way that remembers the time as Stopwatch does. Which should I choose? I have access to SQL server and save it.
Lets say I let it run for 10 seconds since autoreset is true, when I stop it. And then wait, and then start the timer again.
In my opinion, the next time I start the timer it should only run for 10 seconds. So the total time that fires up the event is 20 second and not 30.
Is there any way to "save" elapsed time on it?
public class MySampleClient
{
System.Timers.Timer BatchTimer;
public MySampleClient()
{
BatchTimer = new System.Timers.Timer(BatchSampleTimer) { AutoReset = true };
}
public async Task startSession()
{
BatchTimer.Elapsed += BatchTimerVoid;
}
public void BatchIDTrigger(BatchTagDataModel btdm)
{
string btdmValue = btdm.Value.ToLower();
if (batchNumberTimerControllerList.Contains(btdm.DisplayName))
{
if (btdmValue == "true")
{
BatchTimer.Start();
}
else
{
BatchTimer.Stop();
}
}
}
public void BatchTimerVoid(Object source, System.Timers.ElapsedEventArgs e)
{
// Something happens here every 20 seconds.
}
}
I have written a simple extension to a System.Timers.Timer to provide you with a Pause() method. It uses a backing System.Diagnostics.Stopwatch to modify the Timer.Interval according to the elapsed period before the pause.
public class ExtendedTimer: System.Timers.Timer
{
public long MillisecondsElapsed { get { return backingStopwatch.ElapsedMilliseconds; } }
public new double Interval { get; private set; }
private Stopwatch backingStopwatch;
public ExtendedTimer(double interval) : base(interval)
{
Interval = interval;
backingStopwatch = new Stopwatch();
base.Elapsed += ExtendedTimer_Elapsed;
}
private void ExtendedTimer_Elapsed(object sender, ElapsedEventArgs e)
{
base.Interval = this.Interval;
backingStopwatch.Restart();
}
public new void Start()
{
base.Interval = this.Interval - backingStopwatch.ElapsedMilliseconds;
base.Start();
backingStopwatch.Start();
}
public new void Stop()
{
base.Stop();
backingStopwatch.Reset();
}
public void Pause()
{
base.Stop();
backingStopwatch.Stop();
}
}
Since there is now some overhead introduced, I cannot speak to how accurately it will maintain precision timings compared to the original implementation.

What is the proper way to Dispose of a class with a Timer?

Let's say I have a class which has a Timer object that doesn't do any critical work - just some GUI work. Let's say there are 2 scenarios where the timer elapses every 5 minutes:
in the Timer_Elapsed delegate there is a lot of work that is done and it takes 2 minutes to complete.
in the Timer_Elapsed delegate there is little work to be done and it takes a couple of milliseconds to complete
What is the proper way to dispose of the object & timer? Does the amount of time the Timer_Elapsed event delegate runs influence your decision on how to Dispose properly?
If, you need to stop your timer during disposal, and work could still be in progress in your timer delegate, that relies on shared resources, being disposed at the same time, you need to coordinate the "shutdown" process. The below snippet shows an example of doing this:
public class PeriodicTimerTask : IDisposable
{
private readonly System.Timers.Timer _timer;
private CancellationTokenSource _tokenSource;
private readonly ManualResetEventSlim _callbackComplete;
private readonly Action<CancellationToken> _userTask;
public PeriodicTimerTask(TimeSpan interval, Action<CancellationToken> userTask)
{
_tokenSource = new CancellationTokenSource();
_userTask = userTask;
_callbackComplete = new ManualResetEventSlim(true);
_timer = new System.Timers.Timer(interval.TotalMilliseconds);
}
public void Start()
{
if (_tokenSource != null)
{
_timer.Elapsed += (sender, e) => Tick();
_timer.AutoReset = true;
_timer.Start();
}
}
public void Stop()
{
var tokenSource = Interlocked.Exchange(ref _tokenSource, null);
if (tokenSource != null)
{
_timer.Stop();
tokenSource.Cancel();
_callbackComplete.Wait();
_timer.Dispose();
_callbackComplete.Dispose();
tokenSource.Dispose();
}
}
public void Dispose()
{
Stop();
GC.SuppressFinalize(this);
}
private void Tick()
{
var tokenSource = _tokenSource;
if (tokenSource != null && !tokenSource.IsCancellationRequested)
{
try
{
_callbackComplete.Wait(tokenSource.Token); // prevent multiple ticks.
_callbackComplete.Reset();
try
{
tokenSource = _tokenSource;
if (tokenSource != null && !tokenSource.IsCancellationRequested)
_userTask(tokenSource.Token);
}
finally
{
_callbackComplete.Set();
}
}
catch (OperationCanceledException) { }
}
}
}
Usage example:
public static void Main(params string[] args)
{
var periodic = new PeriodicTimerTask(TimeSpan.FromSeconds(1), cancel => {
int n = 0;
Console.Write("Tick ...");
while (!cancel.IsCancellationRequested && n < 100000)
{
n++;
}
Console.WriteLine(" completed.");
});
periodic.Start();
Console.WriteLine("Press <ENTER> to stop");
Console.ReadLine();
Console.WriteLine("Stopping");
periodic.Dispose();
Console.WriteLine("Stopped");
}
With output like below:
Press <ENTER> to stop
Tick ... completed.
Tick ... completed.
Tick ... completed.
Tick ... completed.
Tick ... completed.
Stopping
Stopped
There are multiple approaches to this, and like Alex said in the comments it depends on whether or not objects the delegate will be using are also disposed.
Let's say we have a "worst-case" scenario, in which the delegate does need to use objects which would be disposed.
A good way to handle this would be similar to a method the Process object has: WaitForExit(). This method would simply loop until it sees the delegate is done working (have a working bool which is set before and after the delegate runs?) then returns. Now you can have something like this in the code using that class:
// Time to shut down
myDisposable.WaitForFinish();
myDisposable.Dispose();
Thus we are essentially ensuring the delegate is done before disposing of it, stopping any sort of ObjectDisposedException.

How to use a Timer to replace Thread.Sleep(...) in an Azure Worker Role?

There's plenty of examples of people saying to use a Timer instead of Thread.Sleep(...) in an Azure Worker Role. No probs with that.
What I'm struggling to understand is how to code this.
Currently, I have the following (pseduo code)
_timer.Elapsed += (sender, args) => DoWork();
public override void Run()
{
while(true)
{
DoWork();
}
}
public void DoWork()
{
try
{
_timer.Stop();
// Now - do stuff ....
}
catch(....) { ... }
_timer.Start()
}
And what happens, is that the code enters the DoWork() method once and DoesStuff(tm).. fine .. starts the timer (say .. with a 30 second interval) and then exits that method.
Then, it returns back to the main Run() method .. which is in that loop. So it immediately comes back around and enters the DoWork() method again .. instead of waiting for the timer to fire it off.
So I'm not sure how to replace any Thread.Sleep(...) with Timers.
Any clues?
Clarification
I do not want to exit the Run() method :) I'm very happy to keep looping forever. What I'm stuck with, is replacing the standard Thread.Sleep(...) call (which blocks the thread) and replace that with a Timer, which most people suggest.
Update
Please do not link or suggest that I should use cancelSource.Token.WaitHandle.WaitOne(); as a solution. That is not what I'm trying to achieve here. Please note the post title!
I figure that if you want to solve this situation the way you outline here you will need a WaitHandle AND a Timer.
The short answer is here below. The long answer became a blog post: HowTo wait in a WorkerRole using Timer and EventWaitHandle over Thread.Sleep
I used an EventWaitHandle along with the Timer and came up with this solution:
public class WorkerRole : RoleEntryPoint
{
Waiter waiter;
public override bool OnStart()
{
waiter = new Waiter(WorkerConfiguration.WaitInterval);
return base.OnStart();
}
public override void Run()
{
while (true)
{
DoWork();
waiter.Wait();
}
}
public void DoWork()
{
// [...]
}
}
And here is the waiter class:
public class Waiter
{
private readonly Timer timer;
private readonly EventWaitHandle waitHandle;
public Waiter(TimeSpan? interval = null)
{
waitHandle = new AutoResetEvent(false);
timer = new Timer();
timer.Elapsed += (sender, args) => waitHandle.Set();
SetInterval(interval);
}
public TimeSpan Interval
{
set { timer.Interval = value.TotalMilliseconds; }
}
public void Wait(TimeSpan? newInterval = null)
{
SetInterval(newInterval);
timer.Start();
waitHandle.WaitOne();
timer.Close();
waitHandle.Reset();
}
private void SetInterval(TimeSpan? newInterval)
{
if (newInterval.HasValue)
{
Interval = newInterval.Value;
}
}
}

Alarm clock application in .Net

I'm not really writing an alarm clock application, but it will help to illustrate my question.
Let's say that I have a method in my application, and I want this method to be called every hour on the hour (e.g. at 7:00 PM, 8:00 PM, 9:00 PM etc.). I could create a Timer and set its Interval to 3600000, but eventually this would drift out of sync with the system clock. Or I could use a while() loop with Thread.Sleep(n) to periodically check the system time and call the method when the desired time is reached, but I don't like this either (Thread.Sleep(n) is a big code smell for me).
What I'm looking for is some method in .Net that lets me pass in a future DateTime object and a method delegate or event handler, but I haven't been able to find any such thing. I suspect there's a method in the Win32 API that does this, but I haven't been able to find that, either.
Or, you could create a timer with an interval of 1 second and check the current time every second until the event time is reached, if so, you raise your event.
You can make a simple wrapper for that :
public class AlarmClock
{
public AlarmClock(DateTime alarmTime)
{
this.alarmTime = alarmTime;
timer = new Timer();
timer.Elapsed += timer_Elapsed;
timer.Interval = 1000;
timer.Start();
enabled = true;
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if(enabled && DateTime.Now > alarmTime)
{
enabled = false;
OnAlarm();
timer.Stop();
}
}
protected virtual void OnAlarm()
{
if(alarmEvent != null)
alarmEvent(this, EventArgs.Empty);
}
public event EventHandler Alarm
{
add { alarmEvent += value; }
remove { alarmEvent -= value; }
}
private EventHandler alarmEvent;
private Timer timer;
private DateTime alarmTime;
private bool enabled;
}
Usage:
AlarmClock clock = new AlarmClock(someFutureTime);
clock.Alarm += (sender, e) => MessageBox.Show("Wake up!");
Please note the code above is very sketchy and not thread safe.
Interesting, I've actually come across a very similar issue and went looking for a method in the .Net framework that would handle this scenario. In the end, we ended up implementing our own solution that was a variation on a while loop w/ Thread.Sleep(n) where n gets smaller the closer you get to the desired target time (logarithmically actually, but with some reasonable thresholds so you're not maxing the cpu when you get close to the target time.) Here's a really simple implementation that just sleeps half the time between now and the target time.
class Program
{
static void Main(string[] args)
{
SleepToTarget Temp = new SleepToTarget(DateTime.Now.AddSeconds(30),Done);
Temp.Start();
Console.ReadLine();
}
static void Done()
{
Console.WriteLine("Done");
}
}
class SleepToTarget
{
private DateTime TargetTime;
private Action MyAction;
private const int MinSleepMilliseconds = 250;
public SleepToTarget(DateTime TargetTime,Action MyAction)
{
this.TargetTime = TargetTime;
this.MyAction = MyAction;
}
public void Start()
{
new Thread(new ThreadStart(ProcessTimer)).Start();
}
private void ProcessTimer()
{
DateTime Now = DateTime.Now;
while (Now < TargetTime)
{
int SleepMilliseconds = (int) Math.Round((TargetTime - Now).TotalMilliseconds / 2);
Console.WriteLine(SleepMilliseconds);
Thread.Sleep(SleepMilliseconds > MinSleepMilliseconds ? SleepMilliseconds : MinSleepMilliseconds);
Now = DateTime.Now;
}
MyAction();
}
}
You could simply reset the timer duration each time it fires, like this:
// using System.Timers;
private void myMethod()
{
var timer = new Timer {
AutoReset = false, Interval = getMillisecondsToNextAlarm() };
timer.Elapsed += (src, args) =>
{
// Do timer handling here.
timer.Interval = getMillisecondsToNextAlarm();
timer.Start();
};
timer.Start();
}
private double getMillisecondsToNextAlarm()
{
// This is an example of making the alarm go off at every "o'clock"
var now = DateTime.Now;
var inOneHour = now.AddHours(1.0);
var roundedNextHour = new DateTime(
inOneHour.Year, inOneHour.Month, inOneHour.Day, inOneHour.Hour, 0, 0);
return (roundedNextHour - now).TotalMilliseconds;
}
You could create an Alarm class which has a dedicated thread which goes to sleep until the specified time, but this will use the Thread.Sleep method. Something like:
/// <summary>
/// Alarm Class
/// </summary>
public class Alarm
{
private TimeSpan wakeupTime;
public Alarm(TimeSpan WakeUpTime)
{
this.wakeupTime = WakeUpTime;
System.Threading.Thread t = new System.Threading.Thread(TimerThread) { IsBackground = true, Name = "Alarm" };
t.Start();
}
/// <summary>
/// Alarm Event
/// </summary>
public event EventHandler AlarmEvent = delegate { };
private void TimerThread()
{
DateTime nextWakeUp = DateTime.Today + wakeupTime;
if (nextWakeUp < DateTime.Now) nextWakeUp = nextWakeUp.AddDays(1.0);
while (true)
{
TimeSpan ts = nextWakeUp.Subtract(DateTime.Now);
System.Threading.Thread.Sleep((int)ts.TotalMilliseconds);
try { AlarmEvent(this, EventArgs.Empty); }
catch { }
nextWakeUp = nextWakeUp.AddDays(1.0);
}
}
}
I know it's a bit of an old question, but I came across this when I was looking for an answer to something else. I thought I'd throw my two cents in here, since I recently had this particular issue.
Another thing you can do is schedule the method like so:
/// Schedule the given action for the given time.
public async void ScheduleAction ( Action action , DateTime ExecutionTime )
{
try
{
await Task.Delay ( ( int ) ExecutionTime.Subtract ( DateTime.Now ).TotalMilliseconds );
action ( );
}
catch ( Exception )
{
// Something went wrong
}
}
Bearing in mind it can only wait up to the maximum value of int 32 (somewhere around a month), it should work for your purposes. Usage:
void MethodToRun ( )
{
Console.WriteLine ("Hello, World!");
}
void CallingMethod ( )
{
var NextRunTime = DateTime.Now.AddHours(1);
ScheduleAction ( MethodToRun, NextRunTime );
}
And you should have a console message in an hour.
What about System.Timers.Timer class ? See http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx
I have used this before with great success:
Vb.net:
Imports System.Threading
Public Class AlarmClock
Public startTime As Integer = TimeOfDay.Hour
Public interval As Integer = 1
Public Event SoundAlarm()
Public Sub CheckTime()
While TimeOfDay.Hour < startTime + interval
Application.DoEvents()
End While
RaiseEvent SoundAlarm()
End Sub
Public Sub StartClock()
Dim clockthread As Thread = New Thread(AddressOf CheckTime)
clockthread.Start()
End Sub
End Class
C#:
using System.Threading;
public class AlarmClock
{
public int startTime = TimeOfDay.Hour;
public int interval = 1;
public event SoundAlarmEventHandler SoundAlarm;
public delegate void SoundAlarmEventHandler();
public void CheckTime()
{
while (TimeOfDay.Hour < startTime + interval) {
Application.DoEvents();
}
if (SoundAlarm != null) {
SoundAlarm();
}
}
public void StartClock()
{
Thread clockthread = new Thread(CheckTime);
clockthread.Start();
}
}
I don't know if the c# works, but the vb works just fine.
Usage in VB:
Dim clock As New AlarmClock
clock.interval = 1 'Interval is in hours, could easily convert to anything else
clock.StartClock()
Then, just add an event handler for the SoundAlarm event.

Categories