|
Quite long time I busy with development of integration none standard hardware with windows software, the software can talk simultaneously with different hardware and above that talk through tcp communication line with other software and other computers. Due to this I am looking for timers which can give better possibility to handle and synchronize such kind processes.
Last time I read about multimedia timers and found on internet this article.
First question which have been raised is how far the multimedia timer is better that let say System.Timers.Timer.
I have built simple test program with two timers. There are instantiated two timer (the class from this article and System.Timers.Timer). Two buttons on the form: Start and stop.
Both buttons start and stop both timers at the same time.
Each timer has own tick event, within the event they write when the event happaned (Console.Writels("Timer 1/2" & Now.TimeOfDay.TotalMilliseconds.tostring))
Both timers always had the same interval. I played with different intervals (5,10,20,50,100,200,500 ms).
The behavior was always the same: at the same time there were events from both timers up to 1 ms precision, no exceptions was found.
Only difference was in multimedia timer:
It gives more events inside the same timestamp. Suppose interval is 5 ms. if the program had not time chunk from CPU then after receiving the chunk the program shows simultaneously 3-4 fired events.
But from mine point of view it is pure waste of computer resources.
So, then is the question: What is advantage of using multimedia timer in comparing with System.Timers.Timer?
The test shows: there are no advantages.
Regards, Jamal
|
|
|
|
|
It sounds like your test is flawed due to its simplicity. Are there any resource-consuming processes or threads running in the background during this test? If not, I would not expect a significant difference in performance between the two timers as the message queue used by the System.Timers.Timer has relatively low traffic and can respond to timer messages in an accurate fashion. Try the same test, but with multiple background threads consuming resources (e.g. performing GUI changes), and see if the results remain the same. If they do, then you may have a point. I certainly have noticed a difference in my graphical application between the two timers.
That being said, it sounds like you are looking for a timer for the synchronization of TCP communication, and I would guess, without experience, that both of these timers are insufficient for that application.
All the best.
|
|
|
|
|
Thank you very much for this code - it's solved a nuggety little issue I was facing in 10 minutes flat instead of hours of doing my own coding. So thanks again.
|
|
|
|
|
Can I start up several instances of the timer? whit key work "new Timer"
br, Patrik
|
|
|
|
|
First of all, thanks for wrapping mmtimer. However, I did some bench marking and here are the results:
Period = 50, Res = 1, Min = 41.308, Max = 61.152, Avg = 49.994
Period = 20, Res = 1, Min = 16.921, Max = 21.685, Avg = 19.996
Period = 10, Res = 1, Min = 4.899, Max = 14.656, Avg = 9.996
Period = 5, Res = 1, Min = 0.033, Max = 17.212, Avg = 4.993
Period = 1, Res = 1, Min = 0.031, Max = 3.503, Avg = 0.993
Period = 1, Res = 1, Min = 0.031, Max = 2.24, Avg = 0.993
Period = 1, Res = 1, Min = 0.032, Max = 2.569, Avg = 0.993
Period = 1, Res = 1, Min = 0.019, Max = 3.452, Avg = 0.992
Period = 1, Res = 1, Min = 0.017, Max = 2.622, Avg = 0.996
I integrated the HiPerfTimer to get the exact tick count since elapsed event. I am not sure where is the problem, but reading msdn about managed vs unmanaged code I can see why the performance degradation.
http://msdn.microsoft.com/en-us/library/ms973872.aspx
Any hints why? I used the mmTimer on native C++ and I used to get exact timing. Wrapping mmTimer in managed code breaks its accuracy. Any help will be greatly appreciated. I apologies if I am double posting of this issue.
thanks
Laith
modified on Thursday, June 10, 2010 1:50 PM
|
|
|
|
|
Hi Leslie,
Just wanted to say thanks very much for providing this class. I've been making an Asteroids-style game and the standard C# timers are far too inconsistent for doing moving graphics. This really helped a lot.
Kind Regards,
Julian
|
|
|
|
|
Hello,
Is this class thead safe ?
Let say the two thread share the same timer, and they both call the stop function, the kill will be called twice on the same timer id, which will cause an assertion. is this right ?
Another thing, lets say that the user used the timer, and supplied slow function that acts as the event hanlde of onStopped. wouldn't it interfere with other instances of the timer ?
thanks,
berlus
|
|
|
|
|
Hi Leslie,
First let me thank you for providing us with this great class. I'm working on an audio/midi sequencer and have been struggling to find a way to get high precision timing firing events.
This class has been written in 2006. Is it still what you would recommend today as the best timer available or have you found something else? Do you know if that is the solution that professional multimedia software developpers would use in their products?
Also, do you know of a way in C# to access the timing capabilities of modern professional audio sound cards (adat, word clock,..)?
Thanks again.
|
|
|
|
|
Hi,
The multimedia timer class is really usefull to me. We use C# on WIN XP32 to control our machines. The main reason is for its 'good' resolution (around 1 ms).
I would like a Wait() function we can call in any thread at any time to wait for the specified time. So there can be multiple waits active at the same time. Since the number of multimedia timers is limited to 16 (I read somewhere) and to reduce the CPU load, (since each multimedia timer creates a thread) I was thinking of using only 1 multimedia timer for this job.
As soon as one calls the Wait() function, it registers the time at which it has to expire and an event to be called when the time has expired. Next the Wait() function will wait until that event gets set. The multimedia timer gets setup for this time and as soon as the timer has expired, it will signal the event for the appropriate wait call. If a 2nd Wait() gets called before the first one has expired and that second timer has to expire before the first one, it should cancel the current multimedia timer and setup the new (shorter) time. As soon as that time has expired it should check if there are other timers expired yet (signal them as well) and finally setup the multimedia timer with the remaining time for the next timer to expire.
Has anyone ever made something like this, or are there other (easier) ways to achive this ?
|
|
|
|
|
Your best bet is to use Query Performance Timer and run it in a separate thread with sleep and set to high priority thread. You can instantiate multiple timers. The mmTimer purpose is method invocation and may not be what you are looking for. There are many articles on Query Performance Timer and I actually used it to get the mmTimer performance (see above posting by me).
|
|
|
|
|
Is 16 instances the upper limit?
|
|
|
|
|
Hi,
Your demo project is different to your source code.
In the demo project, the main form designer is broken.
Also, in neither projects does the timer appear to be a drag-n-droppable component as mentioned in the article :/
|
|
|
|
|
Sk93 wrote: Your demo project is different to your source code.
The source code zip file is only meant to contain the bare minimum of source files, so I only included the Timer.cs file. As far as I can tell (it's been years since I've looked at the code), the Timer.cs file in the source code zip file is identical to that one in the demo zip file.
Sk93 wrote: In the demo project, the main form designer is broken.
There's a dead reference to my StateMachineToolkit assembly. You can delete that, and the demo project should compile fine. Just make sure that the demo is set as the start up project.
Sk93 wrote: Also, in neither projects does the timer appear to be a drag-n-droppable component as mentioned in the article :/
After compiling the Multimedia project, you can add the timer to the toolbox by right clicking on the toolbox and choosing Browse from the dialog box. Then navigate to the Multimedia folder and find the compiled assembly (I think it's in the obj folder). Click on the assembly, and it should be added to the toolbox. From there you can drag n' drop it to your projects.
|
|
|
|
|
Hello, I have problem with accuracy. I try make capturing time with 100ms period:
private void timer1_Tick(object sender, EventArgs e)
{
pole_dat.Add(DateTime.Now);
}
where pole_dat is instance of arraylist
Timer has period 100 and accuracy 1.
Is it possible, thah i make some wrong. Thank you.
Full code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
namespace Vyzarovani
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
ArrayList pole_dat = new ArrayList();
private void button1_Click(object sender, EventArgs e)
{
if (!timer1.IsRunning)
timer1.Start();
else
{
timer1.Stop();
foreach (DateTime polozka in pole_dat)
{
richTextBox1.Text += polozka.ToLongTimeString() + "." + polozka.Millisecond.ToString()+"\n";
}
}
}
private void timer1_Tick(object sender, EventArgs e)
{
pole_dat.Add(DateTime.Now);
}
}
}
|
|
|
|
|
I have found this article and source code very useful. Thank you for taking the time to put it together.
I have an issue that I hope someone can help me with:
In my application, I control hardware devices (e.g. a water pump that keeps a cup of water half full). I need to communicate with the water pump at accurate time intervals (100 milliseconds) to ensure that it keeps the water in the cup at the right level. I don't want to overfill the cup nor do I want the cup to be empty at any time. In order to control the pump correctly, the software needs to communicate with it at accurate time intervals. A periodic multimedia timer appears to be perfect for this job.
Using the sample application from this article, I set the Period to 100 millseconds and the Resolution to 1 milliseconds. When I run the sample application the events are fired at the expected 100ms (+-1ms) intervals. Great!
However, if I then MAXIMISE and MINIMISE the application, everything goes out the window. The MMTimer events are delayed by more than 300 milliseconds !!!
The MMTimer events are also delayed when:
- Opening, closing, minimising, maximising a windows explorer window
- When my screensaver fires up while the application is running. Note: My screensaver displays my photos on the PC, standard windows screensavers do not appear to cause such a big problem.
I investigated further by building a console application (using timeSetEvent etc). Not using a form appears to improve things, but still not all the events are accurate.
Can anyone indicate what is preventing my events from firing at accurate time intervals?? Is there anything that I can do to fix this problem?
Any help is greatly appreciated.
|
|
|
|
|
Windows is not a REALTIME OS. Avery timer can "flash" only if there is empty processing timeslots for its thread. Try to increase process priority level for your application but be careful with hanging your PC.
PS. Sorry for my English: can read, but cant write.
|
|
|
|
|
I want to inherit it
|
|
|
|
|
i have an error when i open the form1 in the demo like this:
Could not find type 'Multimedia.Timer'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built.
and i am looking for answers in the discussion board.
i see "1 2 3 4 5",and i think they are pages, so i click "2" to enter the next page.but system told me i vote 2.
sorry for a mistake.
|
|
|
|
|
You can change your vote by merely selecting one of the other values and clicking the "Vote" button.
|
|
|
|
|
Hello
I found an issue with the design. OneShot Mode does not work if you do not specify a SyncronizingObject. In most cases this is probably ok, it is not a good restriction to live with though.
Thanks,
Patrick
|
|
|
|
|
patrickcbrown wrote: I found an issue with the design. OneShot Mode does not work if you do not specify a SyncronizingObject. In most cases this is probably ok, it is not a good restriction to live with though.
Here's the code from the callback that handles the one shot mode:
if(synchronizingObject != null)
{
synchronizingObject.BeginInvoke(tickRaiser, new object[] { EventArgs.Empty });
Stop();
}
else
{
OnTick(EventArgs.Empty);
Stop();
}
So even if the synchronizingObject is null, the Tick event should still be raised. Have you found this not to be the case?
|
|
|
|
|
Hi
Yes, the tick was raised, the issue in my implementation is that it would only be raised one time because I was calling Start in my TickHandler - which was immediatly followed by your call to Stop(). It is right that it was called once, my issue is that it was not restartable.
Thanks
Patrick
|
|
|
|
|
patrickcbrown wrote: Yes, the tick was raised, the issue in my implementation is that it would only be raised one time because I was calling Start in my TickHandler - which was immediatly followed by your call to Stop(). It is right that it was called once, my issue is that it was not restartable.
Oh, I see! I will have to change that.
|
|
|
|
|
Hi
You know what it is. I use the timer in a ManualReset kind of mode. So, in my tick handler I do some work, change the Period, then tell it to start again. The current TickCallback in your code calls my tick handler, I do my work, then tell the timer to restart, you get control back then tell my started timer to Stop! Darn you - not nice - j/k. I swapped the Stop and OnTick lines, I am in business.
Old Code
<br />
private void TimerOneShotEventCallback(int id, int msg, int user, int param1, int param2)<br />
{<br />
if (synchronizingObject != null)<br />
{<br />
synchronizingObject.BeginInvoke(tickRaiser, new object[] { EventArgs.Empty });<br />
Stop();<br />
}<br />
else<br />
{<br />
<big> OnTick(EventArgs.Empty);<br />
Stop();</big><br />
}<br />
}<br />
New Patrick Brown version
<br />
private void TimerOneShotEventCallback(int id, int msg, int user, int param1, int param2)<br />
{<br />
if (synchronizingObject != null)<br />
{<br />
synchronizingObject.BeginInvoke(tickRaiser, new object[] { EventArgs.Empty });<br />
Stop();<br />
}<br />
else<br />
{ <br />
<big> Stop();<br />
OnTick(EventArgs.Empty);</big><br />
}<br />
}<br />
<br />
Thanks<br />
Patrick<br />
|
|
|
|
|
Hi,
in a C++ program of mine I carried out
timeBeginPeriod before timeSetEvent and accordingly timeEndPeriod after timeKillEvent. I wonder why you haven't done so.
Well - I set breakpoints in timeBeginPeriod/timeEndPeriod and realise, that timeSetEvent or timeKillEvent call timeBeginPeriod or timeEndPeriod, respectively.
However, every single source I found on the internet recommends seperate timeBeginePeriod/timeEndPeriod.
Even the Platform SDK seems to distinguish:
"After you have established your application's timer resolution," [ie, by timeBeginPeriod] "you can start timer events by using the timeSetEvent function.".
What do you think?
Well - before I forget it: Thanks for this great example and demonstration!
|
|
|
|
|