SLEEP that allows automation event-triggers to fire

kriki
Member, Moderator Posts: 9,121
If you use some automation and want to wait for some event to fire, most of the time you use SLEEP. The problem I found is that SLEEP does NOT allow the event-triggers to fire (at least not the ones I found).
So I have invented a method that allows it: I created a function "RealSleep" that allows the event-triggers to fire:
Remarks:
1) the "DosShell"-function you can find here : http://www.mibuso.com/forum/viewtopic.php?t=12417
2) I put the waittime in seconds, and not in milliseconds because the waittime will not be exactly 1 second because of the fact that a file is written and then executed).
So I have invented a method that allows it: I created a function "RealSleep" that allows the event-triggers to fire:
RealSleep(IintSeconds : Integer) // RealSleep // The Navision SLEEP-command blocks automations. // This Sleep does NOT block automations because it uses the WSH shell command // PARAMETERS: // IintSeconds : No. of seconds to do a sleep IF IintSeconds <= 0 THEN EXIT; LtxtCRLF := 'xx'; LtxtCRLF[1] := 10; LtxtCRLF[2] := 13; LtxtTempVBS := GetTemporaryFilename(TRUE,'vbs'); Lfil.WRITEMODE(TRUE); Lfil.TEXTMODE(TRUE); Lfil.QUERYREPLACE(FALSE); Lfil.CREATE(LtxtTempVBS); Lfil.WRITE(STRSUBSTNO('WScript.Sleep %1',IintSeconds * 1000)); Lfil.CLOSE; DosShell('cscript.exe //nologo ' + LtxtTempVBS,0,TRUE); ERASE(LtxtTempVBS);
Remarks:
1) the "DosShell"-function you can find here : http://www.mibuso.com/forum/viewtopic.php?t=12417
2) I put the waittime in seconds, and not in milliseconds because the waittime will not be exactly 1 second because of the fact that a file is written and then executed).
Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!
0
Comments
-
i cant imagine why one would ever need such a thing.
It is time already to change mentality from single flow programming to multi thread event driven programming- you write your code in triggers that respond to some events in the environment your program is living in, the order of those events is a priori unpredictable.
So in case you want to do something like Object.RunAndWaitForResponse where response is a firing of some trigger Object.OnResponseEvent
you should change your program logic fromObject.RunNoWait SLEEP(5000) OR REPEAT UNTIL GotResponse ContinuePlayingWith(Object)
toObject.RunNoWait WaitingForObjectResponseUntil := CURRENTDATETIME+5000 EXIT
and trigger Object.OnResponseEvent code:IF CURRENTDATETIME > WaitingForObjectResponseUntil THEN EXIT; WaitingForObjectResponseUntil := 0DT; //no more waiting ContinuePlayingWith(Object)
0 -
Eugene wrote:
Object.RunNoWait WaitingForObjectResponseUntil := CURRENTDATETIME+5000 EXIT
The problem with this code in Navision is the 3 lines are run and Navision continues with other things WITHOUT waiting.
In general you C/AL code prepares something and then runs the automation.
The command that calls the automation returns immediately WITHOUT waiting for the end of the task the automation should do.
So the C/AL command after the automation-call is run but the automation has not finished yet.
How can I let Navision wait for it?
The only thing I found is:blnTheAutomationFinished := FALSE; REPEAT RealSleep(5); UNTIL blnTheAutomationFinished;
and in some event-trigger of the automatin I put:blnTheAutomationFinished := TRUE;
If you found a better wat, let us know.Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!0 -
The problem with this code in Navision is the 3 lines are run and Navision continues with other things WITHOUT waiting.
Exactlythat's why you do not put any code after (i wrote EXIT to indicate that there is no code below) but instead place the rest of your code (which is supposed to be executed upon getting the response) in the corresponding trigger which receives the response from the object
So the C/AL command after the automation-call is run but the automation has not finished yet.Put the command in the trigger
0 -
Eugene wrote:The problem with this code in Navision is the 3 lines are run and Navision continues with other things WITHOUT waiting.
Exactlythat's why you do not put any code after (i wrote EXIT to indicate that there is no code below) but instead place the rest of your code (which is supposed to be executed upon getting the response) in the corresponding trigger which receives the response from the object
So the C/AL command after the automation-call is run but the automation has not finished yet.Put the command in the trigger
In the last case, if it is a user session, the user can start doing other things. If it is a NAS, other triggers can be fired. So you are not sure that your event-trigger is fired.Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!0 -
the user can start doing other thingsIf it is a NAS, other triggers can be fired.So you are not sure that your event-trigger is fired.0
-
The C/AL code in not re-entrant. This means that the C/AL code can only handle one thing at a time.
Like :
-C/AL command.
-automation call that should process something and only come back when it has finished. If I can't give a parameter to let the automation wait for the end. So I need to put some code after the automation-call to wait until it has finished.
-C/AL command that ONLY should execute when the automation has finished.Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!0 -
The C/AL code in not re-entrant. This means that the C/AL code can only handle one thing at a time
Please can you explain what do you mean by that ?
For example:
i create a form and define a single instance codeunit variable MyCU inside the form and then from form's button i call codeunit's function that creates an automation object MyAO defined in that codeunit and asks that object to do some tasks. I can click the button multiple times and if codeunit is designed to create multiple MyAO and run them then they will execute simultaniously.
When i close the form my understanding is that MyCU variable is destroyed upon exit from the form but MyAO object still exists and continues user's task0 -
First : if you use a singleinstance codeunit, once initialized, the instance will NOT be destroyed by destroying the instance of the object that uses it.
Even more : ALL objects referencing it will use THE SAME instance.
You can test that by defining a global in your singleinstance codeunit and running and object that gives a value to it and then running another objects that asks the value of it. (giving and asking the value must be done through functions in the singleinstance codeunit.
Navision NEVER will execute code at the same time. Like Windows (with a single core singe processor): it seems to be multitasking but in reality it is taskswapping so fast that it seems to be multitasking.
"not re-entrant":
Example : you launched 2 times a pdf-printing automation (in a singleinstance codeunit) and you are waiting for the finishing-event of both. The finishing-event will be called twice (once for each pdf) but in that event, you will NEVER know which of the 2 has finished first! This is the reason you need to wait for the first to finish before launching the second. And thus my repeat-until to wait for it.Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!0 -
The finishing-event will be called twice (once for each pdf) but in that event, you will NEVER know which of the 2 has finished first! This is the reason you need to wait for the first to finish before launching the second.
When calling pdf printing one can check if it is not in process of printing another pdf and ask the user if he wants to launch the second one. If the user chooses to start the second pdf printing then one needs to use a separate automation object for it.
I do agree however that it is much easier to program single-flow than to program multitasking and your REPEAT UNTIL is easier to write. But the idea of asking repeatedly if task is completed is ridiculous - when you give a task to a person you don't come to him every minute asking if he completed the task, instead you simply ask him to report you back when he completes his task0 -
Eugene wrote:when you give a task to a person you don't come to him every minute asking if he completed the task, instead you simply ask him to report you back when he completes his task
It is a NAS that does this work. The NAS would just continue to work on something else (maybe for a long time) and the event-trigger would be postponed a lot because it wouldn't be triggered until the NAS isn't running and C/AL anymore. So this is the reason I didn't want to use your system (although it is more programmatically more correct).Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!0 -
In NAS"the event-trigger would be postponed a lot because it wouldn't be triggered..."
in codeunit 1 on NAS trigger call your single instance codeunit. In codeunit write the following in OnRun trigger:
OnRun()CREATE(Timer);
Timer.Interval(1000);
MESSAGE('My service started at %1 %2',TODAY,TIME);
Timer.Enabled(TRUE);
then in OnTimer tigger:Timer.Enabled := FALSE;
ProcessMyScheduledTasks
Timer.Enabled := TRUE;
So after executing OnRun the NAS can process other requests
but your service is now installed and timer will be called every second to check if there are tasks to be executed by your service0 -
oh almost forgot, you may also want to have this in on TimerError trigger:Timer.Enabled := TRUE;0
-
I know. I am using that technique. But it still won't run the taks in parallel.
If a trigger is fired, no other trigger will be fired UNTIL the first taks is finished.Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!0 -
When you comment out timer enabling/disabling:
//Timer.Enabled := FALSE; ProcessMyScheduledTasks //Timer.Enabled := TRUE;
the timer trigger is not firing but i believe timer events are stacked into Navision's windows messaging queue. Would be interesting to test it - if i keep my task busy for 1 minute will the trigger fire 60 times right after exiting my task or will it fire just once ?0 -
Just once.Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!0
Categories
- All Categories
- 73 General
- 73 Announcements
- 66.6K Microsoft Dynamics NAV
- 18.7K NAV Three Tier
- 38.4K NAV/Navision Classic Client
- 3.6K Navision Attain
- 2.4K Navision Financials
- 116 Navision DOS
- 851 Navision e-Commerce
- 1K NAV Tips & Tricks
- 772 NAV Dutch speaking only
- 617 NAV Courses, Exams & Certification
- 2K Microsoft Dynamics-Other
- 1.5K Dynamics AX
- 320 Dynamics CRM
- 111 Dynamics GP
- 10 Dynamics SL
- 1.5K Other
- 990 SQL General
- 383 SQL Performance
- 34 SQL Tips & Tricks
- 35 Design Patterns (General & Best Practices)
- 1 Architectural Patterns
- 10 Design Patterns
- 5 Implementation Patterns
- 53 3rd Party Products, Services & Events
- 1.6K General
- 1.1K General Chat
- 1.6K Website
- 83 Testing
- 1.2K Download section
- 23 How Tos section
- 252 Feedback
- 12 NAV TechDays 2013 Sessions
- 13 NAV TechDays 2012 Sessions