|
|
Comments and Discussions
|
|
 |

|
this is what i need !
|
|
|
|

|
Reliable, efficient and simple to use!
|
|
|
|

|
Maybe it was a very noob idea, but I wanted to simply replace my normal timer with microtimer...
So I added the class to my project, I created the timer:
public static MicroLibrary.MicroTimer microtimer1 = new MicroLibrary.MicroTimer();
Then I set the value:
microtimer1.Interval = 1;
And I added the method:
microtimer1.MicroTimerElapsed += new MicroLibrary.MicroTimer.MicroTimerElapsedEventHandler(microtimer1_Tick);
private void microtimer1_Tick(object sender, MicroLibrary.MicroTimerEventArgs timerEventArgs)
{
label_time.Text = "Nerds do it better.";
}
And now I get this error:
An unhandled exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll
Additional information: Cross-thread operation not valid: Control 'label_time' accessed from a thread other than the thread it was created on.
What exactly did I do wrong? Thanks a lot!
Martina
|
|
|
|

|
Hi Martina.
The interval is in microseconds (not milliseconds), I expect you meant to write:
microtimer1.Interval = 1000;
If you are updating a UI thread from another thread you will need to use a MethodInvoker:
private void microtimer1_Tick(object sender, MicroLibrary.MicroTimerEventArgs timerEventArgs)
{
if (InvokeRequired)
{
BeginInvoke((MethodInvoker)delegate
{
label_time.Text = "Nerds do it better.";
});
}
}
I will try and update the article to include a win forms example. In the mean time I hope this helps.
Ken.
modified 13-Apr-13 11:16am.
|
|
|
|

|
Hi Martina,
I've now added a WinForms example to the project, I hope this helps!
Ken.
|
|
|
|

|
Not sure what you were trying to accomplish here but you seem to have written a lot about it!
|
|
|
|

|
And I have no idea why you think it only merits a 2. Dave Cross
|
|
|
|

|
Perhaps because he has no idea what it is, and therefor gives it a two. Seriously, why would you rate something 5 stars if you have no idea what it is, or what it does.
|
|
|
|

|
You don't have to give it any stars at all unless you choose to. If you deliberately rate it low, you deliberately flag it as poor quality. I happen to think that if you do that, common courtesy demands that you give an adequate explanation. Making snide remarks (because you have also written an article on the same topic) is just rude. It is also a dis-service to me as a bystander because I have no way to judge what the technical difference between the two approaches is. This is a forum for sensible debate and advice, not for parading ego. Dave Cross
|
|
|
|

|
Welcome to the Internet sir.
There is no such thing as logic here. Same goes with the random dislikes on YouTube videos.
|
|
|
|
|

|
Hi , first of all I would like to thanks you alot. saved my lots of time. And really useful.
I found a small bug while using your micro timer.
It works perfectly fine when I am declaring the timer in the same method in which I am stopping it.
But if I declare it as member of class and 2 different methods are starting and stopping it then it has a small problem.
It starts well and run well too. Problem is with stopping. If I set microtimer.Enabled == false; then it doesnt stop and hangs the application.
I also tried to use microtimer.Stop(); it has the same issue.
WorkAround:
I used the microtimer.Stop(); and commented out following:
while (Enabled)
{
System.Threading.Thread.SpinWait(10);
}
And it solved the problem. I am not a pro. and I dont know what will be the side effects of it but for me its working well . I am using it to generate timer at 256 times in 1 second ( i.e. 256Hz)
|
|
|
|

|
Hi wakaley,
Thanks for the feedback and thanks for your vote, I'm glad the MicroTimer has proved useful.
If implemented correctly, declaring the MicroTimer as a class member and having separate start and stop methods should have no effect on the functionality of the timer. Depending on the implementation, removing the SpinWait while loop in the Stop method may be fine. However, if the timer is hanging in this loop then this means the timer thread (although maybe not doing any 'real' work) is still alive. Thus, removing the SpinWait while loop may be fine but in some cases may lead to undesirable behaviour.
Please note that the amount of work done in the OnTimedEvent must be very small. If the OnTimedEvent calls other methods then these should return immediately and should not keep any handles to the calling thread. If they do then it is entirely possible that the timer thread will always stay alive.
For the point of demonstration, if for example a UI is being updated, then:
This is fine:
private void OnTimedEvent(object sender,
MicroLibrary.MicroTimerEventArgs timerEventArgs)
{
BeginInvoke((MethodInvoker)delegate
{
myWinformsLabel.Text = timerEventArgs.TimerCount.ToString();
});
}
However this is not:
private void OnTimedEvent(object sender,
MicroLibrary.MicroTimerEventArgs timerEventArgs)
{
Invoke((MethodInvoker)delegate
{
myWinformsLabel.Text = timerEventArgs.TimerCount.ToString();
});
}
This is because Control.Invoke executes on the UI thread and the calling thread waits for completion before continuing (i.e. executes synchronously). Whereas Contol.BeginInvoke executes on the UI thread but the calling thread does not wait for completion before continuing (i.e. executes asynchronously).
Having said all of the above, it is certainly true that the current implementation of the MicroTimer Stop method may not be suitable for a number of situations. To this end I will look at revising the Stop method next time I do an update.
I hope this helps.
Ken.
|
|
|
|

|
Excellent implementation which I think should be part of the system itself. THanks a million
|
|
|
|

|
this article - perfect timing! (no pun intended)
|
|
|
|

|
Ha, ha, Thanks for your vote and I hope you find the timer useful.
|
|
|
|

|
You earned this one
|
|
|
|
|

|
if only I had found this last year... it took me some time to realize that the Timer control was not giving any TICK below 16ms approx.. THANKS
|
|
|
|

|
Hi Zaid,
Thanks for your vote. I feel your pain on discovering the hard way the poor resolution offered by the Timer class. I appreciate it is a very hard problem to solve, but I hope one day there will be a main stream operating system (Windows 10 ?!) that will offer RTOS (Real Time Operating System) type behaviour i.e. deterministic timing operations around the 1ms mark.
Ken.
|
|
|
|

|
I doubt Windows BLUE, the next windows to come will have that or the one after it, but if MS is moving more towards the tablet and similar things then this might just become a reality some day....
|
|
|
|
|

|
Hi D-Three,
Firstly thanks very much for your vote, very pleased to hear the MicroTimer has been useful.
Secondly, thanks for pointing out the bug, bit of a 'school boy' error on my part! Next time I do an update I'll definitely include the fix.
Ken.
|
|
|
|
|

|
That's a very good point about changing the Interval and IgnoreEventIfLateBy while the timer is running, I'll definitely look at that when I next do an update. Thanks for the feedback - all very helpful.
|
|
|
|

|
Hi D-Three,
Following your (very helpful) feedback, 'Interval' and 'IgnoreEventIfLateBy' can now be changed whilst the timer is enabled. I've also fixed the unhandled exception error if Stop() is called before Start().
Thanks again, Ken.
|
|
|
|

|
Thanks!
|
|
|
|

|
Thank you guy!
It solved my problem in real time measurements with 200Hz.
|
|
|
|

|
Glad it was helpful and thanks for your vote.
|
|
|
|

|
public long ElapsedMicroseconds
{
get { return (long)(ElapsedTicks / _microSecPerTick); }
}
"ElapsedTicks" should be replaced by "Elapsed.Ticks":
public long ElapsedMicroseconds
{
get { return (long)(Elapsed.Ticks / _microSecPerTick); }
}
|
|
|
|

|
Hi dabalciunas,
The MicroStopwatch class is correct as it is. The Elapsed property returns a TimeSpan, thus it would be possible to replace the ElapsedMicroseconds function with the code below (but not as you suggest).
public long ElapsedMicroseconds
{
get { return (long)(Elapsed.TotalMilliseconds * 1000); }
}
I hope this helps.
Ken.
|
|
|
|

|
Hi, i have test your code stopwatch for generated a quad wave using lpt port.
I've a big problem, when i enable your stopwatch, cpu load going to 100%. For test i've excluded the lpt port code and run only your code and after 1 secondo CPU 100%
I'm the only with this problem?
Thanks
|
|
|
|

|
Hi,
The only way to achieve such a high timer resolution (in the micro/millisecond range) is for the code to sit in a very tight while loop. The consequence of doing this is that a very heavy load is put on the CPU. Thus this is not a bug but simply a side effect of running the timer.
On a multi processor/core machine the operating system will allocate the timer process to one of the available processors and run that processor at near 100%. Thus, for example, on a machine containing 4 CPU's the system will effectively run at 25% CPU loading.
I hope this helps.
Ken.
|
|
|
|

|
For me it's not normal, i know one software can generate a quad signal of 100khx with a dual core cpu and 4%/5% cpu usage.... the only problem of yours timer is this :
you have missed a sleep... but i don't know how to do this because the minimum sleeis 1ms.... i think can it's possible to write a driver with c or assembler for generate a sleep of micro or nanosecondo.
What do you think about this?
|
|
|
|

|
Hi,
In practice the minimum sleep achievable is around the 15ms mark (even if you request 1ms). Instead of a sleep the code uses a 'SpinWait', this is not a sleep but runs for a few nanoseconds and effectively puts the thread to sleep without relinquishing the remainder of its CPU time slot. It is the only solution available in this type of situation and is an optimisation technique used in very tight loops such as a 'lock'.
If there was some hardware to interface with, it may be possible to generate a sleep but once the sleep ends the code would still be at the mercy of the operating system. In addition any hardware driver would be specific to the hardware on that machine.
The fundamental problem is that a conventional operating system (such as Windows) is not able to perform deterministic timing operations. MicroTimer does not and cannot solve this problem, the only way to achieve deterministic timing behaviour is with an RTOS (Real Time Operating System) like IntervalZero RTX:
http://www.directinsight.co.uk/products/venturcom/rtx.html
http://www.intervalzero.com/products/rtx-at-a-glance/
Ken.
|
|
|
|

|
HI ...
use GPU processing for sol this problem
Nvidia Cuda Toolkit
|
|
|
|

|
This is the great job,and I will try this code to control my hardware to enable for 1ms scanning rate.
i have one question, does this code available for c ?
|
|
|
|
|

|
Thanks for the suggestion and information.
I will feed back to you after I test your code in my application. ^^
|
|
|
|

|
Good article It is very interesting for me.
|
|
|
|
|
|
|

|
Hi Ken,
I was testing your Timer class but i've noticed that it's not very stable under my scenario.
Maybe i'm doing something wrong, but i dont think so.
my code is moving the mouse from point A to point B automatically and i use the timer to do a smooth transition.
The thing is that i only want the timer to stop when the mouse reaches the destination point. So i have to put the microTimer.Enabled = false; inside the "Tick" function. However it seems that if i click the start button two times, the first one it works ok but the second one it starts to hang my pc. My guess is that it's not disabling the timer, making it enter on an infinite loop.
Can you tell me what's wrong?
Thanks
public partial class FormMain : Form
{
private const UInt32 MOUSEEVENTF_LEFTDOWN = 0x0002;
private const UInt32 MOUSEEVENTF_LEFTUP = 0x0004;
[DllImport("user32.dll")]
private static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, uint dwExtraInf);
Point startPoint = new Point(980, 520);
Point currentPoint = new Point(0, 0);
Point destinationPoint = new Point(1055, 650);
MicroTimer microTimer = new MicroTimer();
public FormMain()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
currentPoint = startPoint;
Cursor.Position = currentPoint;
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
microTimer = new MicroTimer();
microTimer.MicroTimerElapsed += new MicroTimer.MicroTimerElapsedEventHandler(OnTimedEvent);
microTimer.Interval = 1000;
microTimer.Enabled = true;
}
private void OnTimedEvent(object sender, MicroTimerEventArgs timerEventArgs)
{
if (currentPoint.X!=destinationPoint.X)
currentPoint.X++;
if (currentPoint.Y!=destinationPoint.Y)
currentPoint.Y++;
Cursor.Position = currentPoint;
if (Cursor.Position == destinationPoint) {
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); microTimer.Enabled = false;
}
}
}
|
|
|
|

|
Hi AuspexPT,
You are correct, the timer does enter an infinite loop. The code below should fix your problem:
if (Cursor.Position == destinationPoint) {
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); new System.Threading.Thread(delegate(){ microTimer.Enabled = false; }).Start();
}
I hope this helps.
Ken.
|
|
|
|

|
Yes, it works... Thanks for the help
BTW, why do we need the delegate in this case and not on your example?
|
|
|
|

|
Hi AuspexPT,
Glad to help.
In answer to your question, the other solution would be to remove the while(Enabled){} loop in the MicroTimer Stop() function. When I originally wrote the article I was wondering whether to include the while loop for exactly this situation (I apologise, as on reflection I should have at least added a note in the article indicating this possible scenario). To explain, the while loop waits until the current OnTimedEvent finishes, of cause if the stop (enabled=false) is put inside the OnTimedEvent then the timer could enter an infinite loop (as you discovered). In your implementation removing the while loop in the stop function will be fine but in other implementations this could lead to some undesirable behaviour.
When I get some time I will update the article/code and put some code in to cater for your situation. In the mean time happy coding and thanks for your question.
Ken.
|
|
|
|

|
Hi AuspexPT,
Thought you would like to know that I've updated the project. The MicroLibray should now work with your original code.
Ken.
|
|
|
|

|
hi Ken,
I've done the test, the interval of timer is 1μs, and the cycle of output waveform is about 10μs - 11μs.The following Images were captured from the OSC,
Image1
Image2
Image3
(How to upload images in the reply?? )
The cycle of the waveform was not stable, i guess it's caused by the OS and we have no way to fix it, what's your opinion Ken?
My code is here,
MicroTimer timer;
bool Voltage = false;
public Form1()
{
InitializeComponent();
timer = new MicroTimer();
timer.MicroTimerElapsed += new MicroTimer.MicroTimerElapsedEventHandler(timer_MicroTimerElapsed);
timer.Interval = 1;
timer.Start();
}
void timer_MicroTimerElapsed(object sender, MicroTimerEventArgs timerEventArgs)
{
int data = 0x0;
Voltage = !Voltage;
data ^= Convert.ToInt16(Voltage);
PortAccess.Output(PortAccess.LTP1_REG_DATA, data);
}
modified on Wednesday, August 4, 2010 2:28 AM
|
|
|
|

|
Hi Shem,
Thanks very much for this, this is a really interesting test. Clearly the maximum turnaround time (on your system) is 10μs, it would be interesting to run the test on a faster and/or slower PC and see how the results change. Either way it's difficult to know where the bottle neck / limit is (i.e. software, hardware, OS, etc). For the same reason it's hard to know why the waveform is unstable, however I agree with you that the instability is likely to be caused by the OS (and as such cannot be 'fixed'). To be honest I would not expect it to be that stable at such a small intervals.
If it's easy for you to do, I would be very interested to see the same test results with the interval set at 20μs, 100μs, 1000μs
Thanks again for taking the time to do the tests – really good work.
Ken Johnson, I would be interested in your comments.
Ken.
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
MicroTimer: A microsecond and millisecond timer in C# that is used in a similar way to the .NET System.Timers.Timer.
| Type | Article |
| Licence | CPOL |
| First Posted | 31 Jul 2010 |
| Views | 69,257 |
| Downloads | 5,076 |
| Bookmarked | 142 times |
|
|