private System.Timers.Timer timerSys = new System.Timers.Timer();
ticks are set to start at the beginning of each multiple of 5 seconds
entry exit
10:5:00.146 10:5:00.205
10:5:05.129 10:5:05.177
10:5:10.136 10:5:10.192
10:5:15.140 10:5:15.189
10:5:20.144 10:5:20.204
amd then a delay of 28 second
note that Windows 10 compensates for missing ticks
by firing them at close intervals
10:5:48.612 10:5:48.692
10:5:48.695 10:5:48.745
10:5:48.748 10:5:48.789
10:5:48.792 10:5:49.90
10:5:43.93 10:5:49.131
and another delay of 27 seconds
again Windows 10 crams ticks to compensate
but this time there is an even inside the second tick
that lasts about 28 seconds that makes the tick very long
10:6:16.639 10:6:16.878
this one is very long
10:6:16.883 10:6:42.980
10:6:42.984 10:6:43.236
10:6:43.241 10:6:43.321
10:6:43.326 10:6:43.479
The PC is running just two applications that I wrote.
They communicate via files and also via SQL tables.
This event happens maybe once every two months.
Questions:
What could be happening?
Is there a way to create a log file of all processes over time
My applications keep tabs of the time down to milliseconds.
So if there were a way of logging processes, I could match.
Alternately is there a way for my app to know what the OS is doing.
Related
I wrote:
LocalNotification localNotification = new LocalNotification();
localNotification.setId("Gratitudine");
localNotification.setAlertTitle("Pratica della Gratitudine");
localNotification.setAlertBody("Leggi e ripeti interiormente");
localNotification.setAlertSound("/notification_sound_bell.mp3");
// alert sound file name must begin with notification_sound
Display.getInstance().scheduleLocalNotification(localNotification,
System.currentTimeMillis() + 60 * 1000, // first notification
LocalNotification.REPEAT_MINUTE // Whether to repeat and what frequency
);
It works.
What is a correct way to repeat the notification every ten minutes? The only available options are: REPEAT_NONE, REPEAT_MINUTE, REPEAT_HOUR, REPEAT_DAY, REPEAT_WEEK.
Same question for any arbitrary number of minutes (for example 4 or 13).
Thank you
According to the documentation it doesn't seem to be possible. You can only get it to repeat every minute. To do what you want you may need to setup additional notifications at the intervals. This means that if you want to cancel them you will need to do that when the user clicks on the notification and opens the app, or on some other event.
I want to run a periodic erlang process every 10ms (based on wall clock time), the 10ms should be as accurate as possible; what should be the right way to implement it?
If you want really reliable and accurate periodic process you should rely on actual wall clock time using erlang:monotonic_time/0,1. If you use method in Stratus3D's answer you will eventually fall behind.
start_link(Period) when Period > 0, is_integer(Period) ->
gen_server:start_link({local, ?SERVER}, ?MODULE, Period, []).
...
init(Period) ->
StartT = erlang:monotonic_time(millisecond),
self() ! tick,
{ok, {StartT, Period}}.
...
handle_info(tick, {StartT, Period} = S) ->
Next = Period - (erlang:monotonic_time(millisecond)-StartT) rem Period,
_Timer = erlang:send_after(Next, self(), tick),
do_task(),
{noreply, S}.
You can test in the shell:
spawn(fun() ->
P = 1000,
StartT = erlang:monotonic_time(millisecond),
self() ! tick,
(fun F() ->
receive
tick ->
Next = P - (erlang:monotonic_time(millisecond)-StartT) rem P,
erlang:send_after(Next, self(), tick),
io:format("X~n", []),
F()
end
end)()
end).
If you really want to be as precise as possible and you are sure your task will take less time than the interval you want it performed at you could have one long running process instead of spawning a process every 10ms. Erlang could spawn a new process every 10ms but unless there is a reason you cannot reuse the same process it's usually not worth the overhead (even though it's very little).
I would do something like this in an OTP gen_server:
-module(periodic_task).
... module exports
start_link() ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
... Rest of API and other OTP callbacks
init([]) ->
Timer = erlang:send_after(0, self(), check),
{ok, Timer}.
handle_info(check, OldTimer) ->
erlang:cancel_timer(OldTimer),
Timer = erlang:send_after(10, self(), check),
do_task(), % A function that executes your task
{noreply, Timer}.
Then start the gen_server like this:
periodic_task:start_link().
As long as the gen_server is running (if it crashes so will the parent process since they are linked) the function do_task/0 will be executed almost every 10 milliseconds. Note that this will not be perfectly accurate. There will be a drift in the execution times. The actual interval will be 10ms + time it takes receive the timer message, cancel the old timer, and start the new one.
If you want to start a separate process every 10ms you could have the do_task/0 spawn a process. Note that this will add additional overhead, but won't necessarily make the interval between spawns less accurate.
My example was taken from this answer: What's the best way to do something periodically in Erlang?
This may or may not be a bug, but I would like some help understanding the behavior of Timer.
Here is a test program that sets up Timer.periodic with a duration of 1000 microseconds (1 millisecond). The callback that fires increments a count. Once the count reaches 1000 intervals, the program prints the time elapsed and exits. The point being to get close to 1 second in execution time. Consider the following:
import 'dart:async'
main() {
int count = 0;
var stopwatch = new Stopwatch();
stopwatch.start();
new Timer.periodic(new Duration(microseconds: 1000), (Timer t) {
count++;
if(count == 1000){
print(stopwatch.elapsed);
stopwatch.stop();
}
});
The result is:
0:00:01.002953
That is, just over a second (assuming the remainder is coming from start time of the stopwatch).
However, if you change the resolution to be anything under 1 millisecond e.g. 500 microseconds, the Timer seems to ignore the duration entirely and executes as quickly as possible.
Result being:
0:00:00.008911
I would have expected this to be closer to half a second. Is this an issue with the granularity of the Timer? This issue can also be observed when applying a similar scenario to Future.delayed
The minimal resolution of the timer is 1ms. When asking for a 500ns duration is rounded to 0ms, aka: as fast as possible.
The code is:
int milliseconds = duration.inMilliseconds;
if (milliseconds < 0) milliseconds = 0;
return _TimerFactory._factory(milliseconds, callback, true);
Maybe it should take 1ms as a minimum, if that is its actual minimum, or it should handle microseconds internally, even if it only triggers every 10-15 milliseconds and runs the events pending so far.
If you are in VM it looks like a bug. Please file an issue.
If you are in JS side see the following note on the documentation of the Timer class:
Note: If Dart code using Timer is compiled to JavaScript, the finest granularity available in the browser is 4 milliseconds.
I'm examining some dreadful legacy code that has a Timer event with some lengthy code that contains DoEvents calls. A simplified version looks something like this:
Private Sub tmrProcess_Timer()
'Run some slow processing code here
DoEvents
'More slow code here
DoEvents
'Lots more slow code and the occasional DoEvents here
If booComplete Then
tmrProcess.Enabled = False
End If
End Sub
The timer has it's Interval set to 250 and the slow code could take up to thirty or so seconds to complete. Note that there is a button on the form that sets booComplete = True when it is clicked.
Given that VB6 is single threaded and that timer messages are low priority is it at all possible for the Timer event to be re-entered during a DoEvents call or will the VB6 runtime block execution of a Timer event if the Timer event is currently executing?
This reference has some relevant information. In particular it states that WM_PAINT messages are combined into a single message but there is no mention of whether or not WM_TIMER messages are combined.
i expected it would reenter, but it seems not to
have a look at the following test project:
'1 form with:
' 1 timer control : Name=Timer1
Option Explicit
Private Sub Form_Load()
WindowState = vbMaximized
Timer1.Interval = 2000
End Sub
Private Sub Timer1_Timer()
Static intCount As Integer
Dim sngTime As Single
intCount = intCount + 1
Print CStr(Now) & " Timer event fired " & CStr(intCount)
sngTime = Timer + 3
Do While sngTime > Timer
DoEvents
Loop
Print CStr(Now) & " End of timer event " & CStr(intCount)
End Sub
you will see a "start" 2 seconds after the form loads
you will see an "end" 3 seconds after that
you will see a "start" 2 seconds after the previous "end" showed
you will see an "end" 3 seconds after the "start"
...
if the timer would be reentered i would expect 2 seconds between each "start", but there appears to be 3+2=5 seconds between each "start"
removing the DoEvents doesn't change the behaviour, it just changes the time at which the texts are printed
To avoid reentry, disable the timer till the time taking logic is executed and then enable again.
Private Sub tmrProcess_Timer()
tmrProcess.Enabled = False
'your time taking logic goes here ......
tmrProcess.Enabled = True
End Sub
First, most code containing DoEvents doesn't require it, it's a magical word that people feel compelled to incant (but without without knowing why).
DoEvents allows reentrancy of anything, not just timers.
Your's is a TimerProc. If you had chosen a message then the wm_timer message only comes if the message queue is empty and you ask "are their any messages?". If their is a paint, timer, or mouse move type message pending then if the queue is empty only then are they available.
Despite the obviousnous this is the link it came from:
> mk:#MSITStore:C:\Program%20Files\Microsoft%20Visual%20Studio\MSDN\2001OCT\1033\kbvb.chm::/Source/vbapps/q118468.htm
(of course you have to have same libraries as me installed for this to work.)
Why do you assume the source is the internet?
Definition of DoEvents in Visual Basic for Applications
Q118468
The information in this article applies to:
Microsoft Visual Basic for Applications version 1.0 Microsoft Excel
for Windows, versions 5.0, 5.0c Microsoft Excel for the Macintosh,
versions 5.0, 5.0a Microsoft Excel for Windows 95, versions 7.0, 7.0a
Microsoft Excel 97 for Windows Microsoft Excel 98 Macintosh Edition
SUMMARY The DoEvents function surrenders execution of the macro so
that the operating system can process other events. The DoEvents
function passes control from the application to the operating system.
Some instances in which DoEvents may be useful include the following:
Hardware I/O
Delay Loops
Operating System Calls
DDE Deadlocking
This article also discusses potential problems associated with the
DoEvents function.
MORE INFORMATION
Hardware I/O If your code waits for an input from any I/O device, the
DoEvents function speeds up the application by multitasking. As a
result, the computer does not seems to pause or stop responding (hang)
while the code is executing.
Example:
Open "com1" For Input As #1 Input #1, x Do Until x = Chr(13) DoEvents
'... '... Input #1, x Loop Delay Loops In a delay loop, the DoEvents
function can allow the CPU operating system to continue with any
pending jobs.
Example:
X = Timer() Do While X + 10 > Timer()
DoEventsLoop Operating System Calls When Visual Basic calls the
operating system, the operating system may return the control even
before processing the command completely. Doing so may prevent any
macro code that depends on an object generated by the call from
running. In the example below, the Shell function starts the Microsoft
Word application. If Word is not yet open, any effort to establish a
DDE link to it will halt the code. By using DoEvents, your procedure
makes sure that an operation, such as Shell, is completely executed
before the next macro statement is processed.
Example:
z% = Shell("WinWord Source.Doc",1) DoEvents ... ... DDE Deadlocking
Consider a situation in which a Visual Basic macro calls an
application that is waiting for a second application to get some data.
If the macro does not give control to the second application, the
result is a deadlock. In DDE conversations between multiple
applications, using DoEvents removes the possibility of this type of
deadlocking. Problems Associated with DoEvents Using too many nested
DoEvents statements may deplete the stack space and therefore generate
an "Out of Stack Space" error message. This error is referring to the
application stack space allocated to the Microsoft Excel application.
Make sure the procedure that has given up control with DoEvents is not
executed again from a different part of your code before the first
DoEvents call returns; this can cause unpredictable results.
Once DoEvents relinquishes control to the operating system, it is not
possible to determine when Microsoft Excel will resume the control.
After the operating system obtains control of the processor, it will
process all pending events that are currently in the message queue
(such as mouse clicks and keystrokes). This may be unsuitable for some
real- time data acquisition applications.
REFERENCES For more information about DoEvents, click the Search
button in Help and type:
doevents
Additional query words: Sendkeys keystroke Wait XL98 XL97 XL7 XL5
Keywords : Issue type : Technology : kbHWMAC kbOSMAC kbExcelSearch
kbZNotKeyword6 kbExcel95 kbExcel500 kbExcel98 kbExcel95Search
kbExcel97Search kbExcel98Search kbExcelMacsearch kbVBASearch
kbZNotKeyword3 kbExcel500Mac kbExcel500aMac kbExcel500c kbExcel95a
kbVBA100
Last Reviewed: January 17, 2001 © 2001 Microsoft Corporation. All
rights reserved. Terms of Use.
Send feedback to MSDN.Look here for MSDN Online resources
I'm trying to acquire data from an MCU, save them to a file and plot them. The code functions properly for some time, then just hangs randomly (sometimes after 1 sec, sometimes after 1 minute ...!). Also the serialport timeouts are not respected, i.e. I'm not receiving any timeout exceptions. I'm using an FTDI232RL chip. The only time I get a timeout exception is when I unplug it while the program is running.
Code:
private: System::Void START_Click(System::Object^ sender, System::EventArgs^ e) {
seconds=0;
minutes=0;
hours=0;
days=0;
t=0;
if((this->comboBox4->Text == String::Empty)||(this->textBox2->Text == String::Empty)||(this->textBox3->Text == String::Empty)){
this->textBox1->Text="please select port, save file directory and logging interval";
timer1->Enabled=false;
}
else{ // start assigning
w=Convert::ToDouble(this->textBox3->Text);
double q=fmod(w*1000,10);
if(q!=0){
MessageBox::Show("The logging interval must be a multiple of 0.01s");
}
else{
period=static_cast<int>(w*1000);
this->interval->Interval = period;
try{ // first make sure port isn't busy/open
if(!this->serialPort1->IsOpen){
// select the port whose name is in comboBox4 (select port)
this->serialPort1->PortName=this->comboBox4->Text;
//open the port
this->serialPort1->Open();
this->serialPort1->ReadTimeout = period+1;
this->serialPort1->WriteTimeout = period+1;
String^ name_ = this->serialPort1->PortName;
START=gcnew String("S");
this->textBox1->Text="Logging started";
timer1->Enabled=true;
interval->Enabled=true;
myStream=new ofstream(directory,ios::out);
*myStream<<"time(ms);ADC1;ADC2;ADC3;ADC4;ADC5;ADC6;ADC7;ADC8;";
*myStream<<endl;
chart1->Series["ADC1"]->Points->Clear();
chart1->Series["ADC2"]->Points->Clear();
chart1->Series["ADC3"]->Points->Clear();
chart1->Series["ADC4"]->Points->Clear();
chart1->Series["ADC5"]->Points->Clear();
chart1->Series["ADC6"]->Points->Clear();
chart1->Series["ADC7"]->Points->Clear();
chart1->Series["ADC8"]->Points->Clear();
backgroundWorker1->RunWorkerAsync();
}
else
{
this->textBox1->Text="Warning: port is busy or isn't open";
timer1->Enabled=false;
interval->Enabled=false;
}
}
catch(UnauthorizedAccessException^)
{
this->textBox1->Text="Unauthorized access";
timer1->Enabled=false;
interval->Enabled=false;
}
}
}
}
private: System::Void backgroundWorker1_DoWork(System::Object^ sender, System::ComponentModel::DoWorkEventArgs^ e) {
while(!backgroundWorker1->CancellationPending){
if(backgroundWorker1->CancellationPending){
e->Cancel=true;
return;
}
t+=period;
if(t<10*period){
this->chart1->ChartAreas["ChartArea1"]->AxisX->Minimum=0;
this->chart1->ChartAreas["ChartArea1"]->AxisX->Maximum=t+10*period;
}
else {
this->chart1->ChartAreas["ChartArea1"]->AxisX->Minimum=t-10*period;
this->chart1->ChartAreas["ChartArea1"]->AxisX->Maximum=t+10*period;
}
*myStream<<t<<";";
for (int n=0;n<8;n++){
adc_array[n]= this->serialPort1->ReadByte();
}
Array::Copy(adc_array,ADC,8);
for(int f=0; f<8; f++){
*myStream<<ADC[f]<<";";
}
*myStream<<endl;
backgroundWorker1->ReportProgress(t);
}
}
private: System::Void backgroundWorker1_ProgressChanged(System::Object^ sender, System::ComponentModel::ProgressChangedEventArgs^ e) {
chart1->Series["ADC1"]->Points->AddXY(t,ADC[0]);
chart1->Series["ADC2"]->Points->AddXY(t,ADC[1]);
chart1->Series["ADC3"]->Points->AddXY(t,ADC[2]);
chart1->Series["ADC4"]->Points->AddXY(t,ADC[3]);
chart1->Series["ADC5"]->Points->AddXY(t,ADC[4]);
chart1->Series["ADC6"]->Points->AddXY(t,ADC[5]);
chart1->Series["ADC7"]->Points->AddXY(t,ADC[6]);
chart1->Series["ADC8"]->Points->AddXY(t,ADC[7]);
}
the user is allowed to define intervals in seconds for data acquisition (in the code this interval is w after conversion to double). In this case, the program sends a pulse to the MCU requesting a new data transmission. So far, I have been testing this for 1 second intervals (note, during each interval the MCU sends 8 frames, each representing an ADC). However, I need to get this to run for 10ms intervals at some point. Will this be possible? Any idea on how to solve the few problems I mentioned at the beginning?
Thanks in advance
UPDATE
Just to give you an idea of what's happening:
I commented the charting part and ran the program for about 5 minutes, with a reading interval of 1s. So I expected to get around 5x60=300 values in the output file, but I only got 39 (i.e. starting from 1s till 39s). The program was still running, but the data were not getting stored anymore.
Testing was done in release mode and not debug mode. In debug mode, setting a break point under serialport->readbyte(), does not reproduce the problem. My guess is it's a timing issue between program and MCU.
You are making several standard mistakes. First off, do NOT unplug the cable when the port is opened. Many USB emulators don't know how to deal with that, the FTDI driver is particularly notorious about that. They just make the port disappear while it is in use, this invariably gives code that uses the port a severe heart attack. An uncatchable exception is common.
Secondly, you are accessing properties of a class that is not thread-safe in a worker thread. The Chart control was made to be used only in a UI thread, accessing the ChartAreas property in a worker is going to buy you a lot of misery. Getting an InvalidOperationException is pretty typical when you violate threading requirements, it is however not consistently implemented. Nastiness includes random AccessViolationExceptions, corrupted data and deadlock.
Third, you are setting completely unrealistic goals. Pursuing an update every 10 milliseconds is pointless, the human eye cannot perceive that. Anything past 50 milliseconds just turns into a blur. Something that is taken advantage of when you watch a movie in the cinema, it displays at 24 frames per second. The failure mode for that is unpleasant as well, you'll eventually reach a point where you are pummeling the UI thread (or the Chart control) with more updates than it can process. The side effect is that the UI stops painting itself, it is too busy trying to keep up with the deluge of invoke requests. And the amount of memory your program consumes keeps building, the update queue grows without bounds. That does eventually end with an OOM exception, it takes a while to consume 2 jiggabytes however. You will need to prevent this from happening, you need to throttle the rate at which you invoke. A simple thread-safe counter can take care of that.
Forth, you are accessing the data you gather in more than one thread without taking care of thread-safety. The ADC array content is being changed by the worker while the UI thread is reading it. Various amounts of misery from that, bad data at a minimum. A simply workaround is to pass a copy of the data to the ReportProgress method. In general, address these kind of threading problems by using pull instead of push. Get rid of the fire-hose problem by having the UI thread pace the requests instead of trying to have the UI thread keep up.