Time driven actions with .Net Class Timer

Till Nav 2009 if time driven actions were needed, it was done using automation NTimer.dll (NavTimer). With Nav 2013 and newer Versions Microsoft recommends to avoid usage of automations. As a result many of the common used automations, shipped with Nav 2009 and earlier, disappeared. There are few descriptions, how to solve common issues formerly solved with automations. So, let’s have a look at the Timer issue.

The .Net Framework contains class System.Timers.Timer in assembly System.dll. To use and test it, create a new codeunit and add some global variables:

sc10

Variable Timer is of subtype System.Timers.Timer. We set properties RunOnClient to false, but WithEvents to true. Only one of these properties can be set to true at one time, both together is not allowed. But ok, we need the Triggers (in .Net called Events). With RunOnClient=false, the code runs on the server … and that’s ok. Setting WithEvents to true we get automatically all embedded .Net Events written in the C/AL code, in that case Timer::Elapsed(sender : Variant;e : DotNet “System.Timers.ElapsedEventArgs”) and Timer::Disposed(sender : Variant;e : DotNet “System.EventArgs”). We only use the first one.

In the sample we want create a file and write lines into the file, step by step, every 3 seconds one line. We use a Counter for a break condition.

OnRun()
Counter := 0; // Counter is an Integer variable

MESSAGE('Timer started');
IF EXISTS('c:\temp\sample.txt') THEN
  ERASE('c:\temp\sample.txt'); // delete the file, if it already exists
TextFile.CREATE('c:\temp\sample.txt'); // TextFile is a FILE variable
TextFile.TEXTMODE := TRUE;

Timer := Timer.Timer(); // create a Timer instance
Timer.Interval := 3000; // i.e. 3 secs (unit is ms)
Timer.Enabled := TRUE;
Timer.Start(); // starts the timer

Timer::Elapsed(sender : Variant;e : DotNet "System.Timers.ElapsedEventArgs")
Counter := Counter + 1;
TextFile.WRITE('line ' + FORMAT(Counter) + ', ' + FORMAT(TODAY) + ' ' + FORMAT(TIME));

// stop timer after trigger Elapsed was called 10 times
IF Counter > 10 THEN BEGIN
  Timer.Enabled := FALSE;
  Timer.Stop(); // stops the timer
  Timer.Close();
  CLEAR(Timer);
  TextFile.CLOSE;
END;

Result:

sc11

cheers

Advertisements

2 thoughts on “Time driven actions with .Net Class Timer

  1. A couple of questions here. I have used this solution on a PAGE. I have a button to START the timer and a button to STOP the timer on this page.

    1) In Timer::Elapsed I tried to do a CurrPage.UPDATE, but the page does not update. I must hit the REFRESH button on the page.

    2) If I STOP the timer and hit REFRESH the client crashes with the Event Viewer showing the text below:

    StackTrace:
    bei Microsoft.Dynamics.Nav.Runtime.SessionAccessLock.ThrowSessionTerminatedException()
    bei Microsoft.Dynamics.Nav.Runtime.SessionAccessLock.BeginCallStackExecution()
    bei Microsoft.Dynamics.Nav.Service.ServiceCallStack.Push()
    bei Microsoft.Dynamics.Nav.Service.ServiceOperationInvoker.PushPopCombinator(ServiceOperation innerOperation, NSServiceBase serviceInstance, Object[] inputs, Object[]& outputs)
    Source: Microsoft.Dynamics.Nav.Ncl
    HResult: -2146233088

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s