|
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!
|
|
|
|
|
Hello and thank you for the code.
I also think you have to explicitly call timeBeginPeriod and timeEndPeriod.
I started out to use this class but didn't get the desired effect, there was a lot of jitter in my output signals. I use the multimedia timer to switch off the transmitter with RTS in a half duplex RS485 application. Changing the resolution parameter didn't seem to change anything. I stripped down everything and just used timeSetEvent as a one shot timer and a callback function. This still didn't change anything.
All of a sudden all seemed to work just fine. Rock solid timing events with no jitter. At first I didn't understad what had changed but it turned out to be a multimeda application running in the background. In this case it was Quick Time player that was started and running in the background (paused though).
Closing Quick Time player got my jitter back. Calling timeBeginPeriod with the desired reolution before using the timer fixed it.
Just thought I should mention it if there are others with the same problem.
Again, thanks for the code.
/Ruben
|
|
|
|
|
I loaded the demo project in VS 2005 and tried to look at Form1.cs in the designer. I got the following errors:
Warning 1 The path is not of a legal form. 0 0
Warning 2 Could not resolve this reference. Could not locate the assembly "StateMachineToolkit". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors. MultimediaTimerDemo
Warning 3 The referenced component 'StateMachineToolkit' could not be found.
It also didn't display the form but just an error message about "The path is not of a legal form".
I can run the demo though and it displays the form correctly.
Other than that, this seems to be a great contribution. Very well written and commented as far as I can tell. I'm still studying it -- I haven't figured out how to "drag and drop" it as a component yet, but I will figure it out...
Thanks!
David Messer
mailto:DLMSoftware@pobox.com
|
|
|
|
|