473,834 Members | 2,255 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

C# Timer tick inaccurate with progressbar

6 New Member
Hi

I'm fairly new to .Net programming so I'll try to explain my problem as easy as I can, and in advanced sorry for my poor english.

I've got some spare hours where I work, so I've decided to spend them learning C# .Net.
I've done some smaller programming assignments and decided now to try a larger program.

I'm trying to create a basic game where you the "hero" meets "villains" and monsters in an arena. I want the fighting to be like final fantasy (for those of you who have played it), after each attack you have to wait some seconds before you can attack again(depending on the speed of your weapon).
Here is where my problem lies, I can't get the timer to be accurate. I'll try to explain.

-I got this windows form: Arena, which loads in the player and monster when certain buttons are pressed.

- When all is set, you press the "Fight" button.
Expand|Select|Wrap|Line Numbers
  1. private void FightBtn_Click(object sender, EventArgs e)
  2. {
  3.             Thread playerAttack = new Thread(new ThreadStart(startPlayer));
  4.             Thread monsterAttack = new Thread(new ThreadStart(startMonster));
  5.             playerAttack.Start();
  6.             monsterAttack.Start();
  7. }
  8.  
I want the player and monster to run in threads, so they run independent of each other.

-The monster thread is not importent right now, so I'll just follow the player thread.
Expand|Select|Wrap|Line Numbers
  1. public delegate void new_startPlayer_delegate();
  2.  
  3. private void startPlayer()
  4. {
  5.     Invoke(new new_startPlayer_delegate(new_startPlayer));
  6. }
  7.  
  8. public void new_startPlayer()
  9. {
  10.    playerAttackPnl.Visible = true;            
  11.    PlayerTimer.Tick += new EventHandler(PlayerTimer_Tick);
  12. }
  13.  
I'll explain the PlayerTimer.Tic k later.
playerAttackPnl is a panel which contains a button called playerattackBtn .
Expand|Select|Wrap|Line Numbers
  1. private void playerattackBtn_Click(object sender, EventArgs e)
  2. {
  3. playerattackBtn.Visible = false;
  4. PlayerTimer.Interval = 100;
  5. playerProgressbar.Maximum = 50;
  6. startTime = DateTime.Now;
  7. PlayerTimer.Enabled = true;
  8. PlayerTimer.Start()
  9. }
  10.  
I have a Windows.Form.Ti mer called PlayerTimer and a progressbar called playerProgressb ar.
So I set the timer interval to 100 and progressbar maximum to 50.
startTime is a datetime and I use it to measure the time.
I also set the button visible to false, so you cant press it again.

-Then we have the PlayerTimer_Tic k method.
Expand|Select|Wrap|Line Numbers
  1. private void PlayerTimer_Tick(object sender, EventArgs e)
  2. {
  3.             playerProgressbar.Increment(1);
  4.             if (playerProgressbar.Value >= playerProgressbar.Maximum)
  5.             {
  6.                 PlayerTimer.Stop();
  7.                 PlayerTimer.Enabled = false;
  8.                 playerProgressbar.Value = 0;
  9.                 playerattackBtn.Visible = true;
  10.                 stopTime = DateTime.Now;
  11.                 TimeSpan time = stopTime.Subtract(startTime);
  12.                 MessageBox.Show(Convert.ToString(time));
  13.             }
  14. }
  15.  
So each time the tick fires, I increase the progressbar value with 1 and check if it has reached maximum. If it has, I stop the timer, disable it, set progressbarvalu e to 0, show the attack button again and calculate the time this has taken.

The reason I added this "PlayerTimer.Ti ck += new EventHandler(Pl ayerTimer_Tick) ;" in the "public void new_startPlayer ()" method is because I experienced if I had it in the button click method, the runtime got faster and faster and faster for each run. This I don't know why, maybe some of you know?

But anyhow, now we have a timer with interval 100, and a progress bar who counts to 50, correct me if I'm wrong, but shoulnt this take 5 second?
When I run this, it takes: 2,73455 sec.

If I change the interval to 1000 and max to 10 it takes 5 sec.
Interval 50 and max 100 = 3,1252 sec.

Where am I doing wrong?
I've also tried with System.Timers.T imer, and still not accurate.

Ask if something is unclear.

Thanks in advanced :)

Marius
Mar 4 '08 #1
9 7297
shweta123
692 Recognized Expert Contributor
Hi,

Before the progressbar you should first set the following properties of the progressbar :

1) progressBar1.Ma ximum
2) progressBar1.Mi nimum
3) progressBar1.St ep
4) progressBar1.Va lue

Now in your code , you should set the above properties to the following values:

private void playerattackBtn _Click(object sender, EventArgs e)
{
playerattackBtn .Visible = false;
PlayerTimer.Int erval = 100;
playerProgressb ar.Maximum = 50;
playerProgressb ar.Minimum= 0;
playerProgressb ar.Value= 0;

startTime = DateTime.Now;
PlayerTimer.Ena bled = true;
PlayerTimer.Sta rt()
}

To increment the value of the progressbar you can use one of the following methods :
1) Use increment() method.
e.g. progressbar1.in crement(1);
2) Increment the value of progressbar using its Value property.
e.g. progressBar1.Va lue += 1;

So , in your code you may try it like this :

private void PlayerTimer_Tic k(object sender, EventArgs e)
{
playerProgressb ar.value +=1;
............... ..
}





Hi

I'm fairly new to .Net programming so I'll try to explain my problem as easy as I can, and in advanced sorry for my poor english.

I've got some spare hours where I work, so I've decided to spend them learning C# .Net.
I've done some smaller programming assignments and decided now to try a larger program.

I'm trying to create a basic game where you the "hero" meets "villains" and monsters in an arena. I want the fighting to be like final fantasy (for those of you who have played it), after each attack you have to wait some seconds before you can attack again(depending on the speed of your weapon).
Here is where my problem lies, I can't get the timer to be accurate. I'll try to explain.

-I got this windows form: Arena, which loads in the player and monster when certain buttons are pressed.

- When all is set, you press the "Fight" button.
Expand|Select|Wrap|Line Numbers
  1. private void FightBtn_Click(object sender, EventArgs e)
  2. {
  3.             Thread playerAttack = new Thread(new ThreadStart(startPlayer));
  4.             Thread monsterAttack = new Thread(new ThreadStart(startMonster));
  5.             playerAttack.Start();
  6.             monsterAttack.Start();
  7. }
  8.  
I want the player and monster to run in threads, so they run independent of each other.

-The monster thread is not importent right now, so I'll just follow the player thread.
Expand|Select|Wrap|Line Numbers
  1. public delegate void new_startPlayer_delegate();
  2.  
  3. private void startPlayer()
  4. {
  5.     Invoke(new new_startPlayer_delegate(new_startPlayer));
  6. }
  7.  
  8. public void new_startPlayer()
  9. {
  10.    playerAttackPnl.Visible = true;            
  11.    PlayerTimer.Tick += new EventHandler(PlayerTimer_Tick);
  12. }
  13.  
I'll explain the PlayerTimer.Tic k later.
playerAttackPnl is a panel which contains a button called playerattackBtn .
Expand|Select|Wrap|Line Numbers
  1. private void playerattackBtn_Click(object sender, EventArgs e)
  2. {
  3. playerattackBtn.Visible = false;
  4. PlayerTimer.Interval = 100;
  5. playerProgressbar.Maximum = 50;
  6. startTime = DateTime.Now;
  7. PlayerTimer.Enabled = true;
  8. PlayerTimer.Start()
  9. }
  10.  
I have a Windows.Form.Ti mer called PlayerTimer and a progressbar called playerProgressb ar.
So I set the timer interval to 100 and progressbar maximum to 50.
startTime is a datetime and I use it to measure the time.
I also set the button visible to false, so you cant press it again.

-Then we have the PlayerTimer_Tic k method.
Expand|Select|Wrap|Line Numbers
  1. private void PlayerTimer_Tick(object sender, EventArgs e)
  2. {
  3.             playerProgressbar.Increment(1);
  4.             if (playerProgressbar.Value >= playerProgressbar.Maximum)
  5.             {
  6.                 PlayerTimer.Stop();
  7.                 PlayerTimer.Enabled = false;
  8.                 playerProgressbar.Value = 0;
  9.                 playerattackBtn.Visible = true;
  10.                 stopTime = DateTime.Now;
  11.                 TimeSpan time = stopTime.Subtract(startTime);
  12.                 MessageBox.Show(Convert.ToString(time));
  13.             }
  14. }
  15.  
So each time the tick fires, I increase the progressbar value with 1 and check if it has reached maximum. If it has, I stop the timer, disable it, set progressbarvalu e to 0, show the attack button again and calculate the time this has taken.

The reason I added this "PlayerTimer.Ti ck += new EventHandler(Pl ayerTimer_Tick) ;" in the "public void new_startPlayer ()" method is because I experienced if I had it in the button click method, the runtime got faster and faster and faster for each run. This I don't know why, maybe some of you know?

But anyhow, now we have a timer with interval 100, and a progress bar who counts to 50, correct me if I'm wrong, but shoulnt this take 5 second?
When I run this, it takes: 2,73455 sec.

If I change the interval to 1000 and max to 10 it takes 5 sec.
Interval 50 and max 100 = 3,1252 sec.

Where am I doing wrong?
I've also tried with System.Timers.T imer, and still not accurate.

Ask if something is unclear.

Thanks in advanced :)

Marius
Mar 4 '08 #2
appelsinagurk
6 New Member
Hi

Thanks for quick response.

I've done what you said, but it still doesnt work.


I've tried both: playerProgressb ar.increment(1) ; and
playerProgressb ar.Value += 1;
playerProgressb ar.step is 1.

But still returns the same value: 2, 7343 sec when interval is 100 and maximum is 50.

Regards
Marius

Hi,

Before the progressbar you should first set the following properties of the progressbar :

1) progressBar1.Ma ximum
2) progressBar1.Mi nimum
3) progressBar1.St ep
4) progressBar1.Va lue

Now in your code , you should set the above properties to the following values:

private void playerattackBtn _Click(object sender, EventArgs e)
{
playerattackBtn .Visible = false;
PlayerTimer.Int erval = 100;
playerProgressb ar.Maximum = 50;
playerProgressb ar.Minimum= 0;
playerProgressb ar.Value= 0;

startTime = DateTime.Now;
PlayerTimer.Ena bled = true;
PlayerTimer.Sta rt()
}

To increment the value of the progressbar you can use one of the following methods :
1) Use increment() method.
e.g. progressbar1.in crement(1);
2) Increment the value of progressbar using its Value property.
e.g. progressBar1.Va lue += 1;

So , in your code you may try it like this :

private void PlayerTimer_Tic k(object sender, EventArgs e)
{
playerProgressb ar.value +=1;
............... ..
}
Mar 4 '08 #3
shweta123
692 Recognized Expert Contributor
Hi,

I think the difference in the no of seconds is coming because
you are calculating startTime in the procedure playerattackBtn _Click(). Instead of this if you calculate startTime in PlayerTimer_Tic k() procedure you might get the correct result.

e.g.

private void PlayerTimer_Tic k(object sender, EventArgs e)
{
if(startTime == "")
{
//set the startTime value here when timer starts
startTime = DateTime.Now;
}
playerProgressb ar.Increment(1) ;
if (playerProgress bar.Value >= playerProgressb ar.Maximum)
{
PlayerTimer.Sto p();
PlayerTimer.Ena bled = false;
playerProgressb ar.Value = 0;
playerattackBtn .Visible = true;
stopTime = DateTime.Now;
TimeSpan time = stopTime.Subtra ct(startTime);
MessageBox.Show (Convert.ToStri ng(time));
}
}




Hi

Thanks for quick response.

I've done what you said, but it still doesnt work.


I've tried both: playerProgressb ar.increment(1) ; and
playerProgressb ar.Value += 1;
playerProgressb ar.step is 1.

But still returns the same value: 2, 7343 sec when interval is 100 and maximum is 50.

Regards
Marius
Mar 4 '08 #4
appelsinagurk
6 New Member
Nope, still didnt work, got the same value: 2,73.
Correct me if I'm wrong but when you have interval = 100 and maximum = 50, you go one step each tick, shouldnt the time running this be 5 sec?
Then 2,73 is pretty far off. Cant be a minor code delay, I must have typed something wrong somewhere.
The problem is to find out where.

Regards
Marius

Hi,

I think the difference in the no of seconds is coming because
you are calculating startTime in the procedure playerattackBtn _Click(). Instead of this if you calculate startTime in PlayerTimer_Tic k() procedure you might get the correct result.

e.g.

private void PlayerTimer_Tic k(object sender, EventArgs e)
{
if(startTime == "")
{
//set the startTime value here when timer starts
startTime = DateTime.Now;
}
playerProgressb ar.Increment(1) ;
if (playerProgress bar.Value >= playerProgressb ar.Maximum)
{
PlayerTimer.Sto p();
PlayerTimer.Ena bled = false;
playerProgressb ar.Value = 0;
playerattackBtn .Visible = true;
stopTime = DateTime.Now;
TimeSpan time = stopTime.Subtra ct(startTime);
MessageBox.Show (Convert.ToStri ng(time));
}
}
Mar 4 '08 #5
Plater
7,872 Recognized Expert Expert
Everytime you add an event handler, it will do just that ADD ANOTHER event handler, so the first run with get a single eventhandler, the 2nd run will get two and so on and so.
Meaning the speed is cut in half each time.
An interval of 100 is 1/10 of a second, so you should be getting a 5second total wait time.

Only add the event handler ONCE and don't do it again, unless you remove it (which i think is almost identical commands except instead of += you say -=)
Mar 4 '08 #6
appelsinagurk
6 New Member
Thanks alot :)

The event got created in the background when the form loaded, so I just had to remove the event in my code.
The time is still of by 0,4 but I'm sure it just has something to do with where I start and stop my timecount.

Regards
Marius

Everytime you add an event handler, it will do just that ADD ANOTHER event handler, so the first run with get a single eventhandler, the 2nd run will get two and so on and so.
Meaning the speed is cut in half each time.
An interval of 100 is 1/10 of a second, so you should be getting a 5second total wait time.

Only add the event handler ONCE and don't do it again, unless you remove it (which i think is almost identical commands except instead of += you say -=)
Mar 4 '08 #7
shweta123
692 Recognized Expert Contributor
Hi,

I have two suggestions :

1) You can try DateDiff function for calculating the difference in time.
e.g. DateDiff("s", startTime, stopTime) .

2) Also , in your code you are checking for progressbar value >= progressbar.max imum. Instead of this you can compare it using progressbar value = progressbar.max imum

Nope, still didnt work, got the same value: 2,73.
Correct me if I'm wrong but when you have interval = 100 and maximum = 50, you go one step each tick, shouldnt the time running this be 5 sec?
Then 2,73 is pretty far off. Cant be a minor code delay, I must have typed something wrong somewhere.
The problem is to find out where.

Regards
Marius
Mar 4 '08 #8
appelsinagurk
6 New Member
I think I've figured out why the time is so off.

When I use long intervals and small progressbar.max I get an accurate time.
e.g. interval = 1000 and max = 5 equals 5,000067 sec
but when I use interval 100 and max = 50 I get 5,75

So the more steps you have, the more the "left over" time 000067 gets accumulated into a bigger off time.

Which brings me to my next question, If I use longer intervals and smaller max values, the progressbar jumps 1/3 for each tick, this does not look very nice. Is there a way to get it to go smooth?
I've tried using the style=continuou s on the progressbar properties with no luck.

Regards
Marius

Hi,

I have two suggestions :

1) You can try DateDiff function for calculating the difference in time.
e.g. DateDiff("s", startTime, stopTime) .

2) Also , in your code you are checking for progressbar value >= progressbar.max imum. Instead of this you can compare it using progressbar value = progressbar.max imum
Mar 5 '08 #9
appelsinagurk
6 New Member
I was wrong, I found out that the program ran an extra tick.

So interval 1000 and max 5 became 6 sec

So thats why the time is so off when using large max values, another tick is fired after the code is supposed to be finished.


I think I've figured out why the time is so off.

When I use long intervals and small progressbar.max I get an accurate time.
e.g. interval = 1000 and max = 5 equals 5,000067 sec
but when I use interval 100 and max = 50 I get 5,75

So the more steps you have, the more the "left over" time 000067 gets accumulated into a bigger off time.

Which brings me to my next question, If I use longer intervals and smaller max values, the progressbar jumps 1/3 for each tick, this does not look very nice. Is there a way to get it to go smooth?
I've tried using the style=continuou s on the progressbar properties with no luck.

Regards
Marius
Mar 5 '08 #10

Sign in to post your reply or Sign up for a free account.

Similar topics

4
4409
by: Christine | last post by:
I've implemented a countdown timer for a tutorial web page that should give the user 45 minutes to complete the test, only to find that the timer is slowly 'losing' time. On average, it actually takes an extra 35 seconds, but has taken an extra 2.5 minutes in some cases. Any ideas what might be the cause? And more importantly - the fix? Code snippet below... Thanks, Christine
14
2565
by: Crirus | last post by:
This is more a logical problem than a VB. I have this situation: A timer that need to tick at each 10 minutes starting on minute 15 of curent hour. But I want to calculate the next tick time whenever I want to start the timer.
7
2387
by: Noozer | last post by:
I have a timer on a form. It isn't firing at all. I know that the timer is enabled, and that the interval is low (4000, which should be 4 seconds). To ensure the timer wasn't being inadvertantly reset I put some extra code in the subs that enable and disable the timer. They fire as expected. To test this I added a second timer with a 1 second interval. The event for this time would output the enabled status of the first timer and its...
10
1844
by: Bob | last post by:
I have a splashscreen running on a thread from Sub Main and it works OK. It displays information in a statusbar about queries. I also have a time on the splashscreen, but the tick event never gets fired. In the Load Event if the splashscreen I call the timer's Start() event. HOw do I get the tick event to fire?
2
2381
by: Bernie Yaeger | last post by:
I'm trying to create a custom control that contains both a combobox and a timer. Any ideas how I can accomplish this? I do know how to create a 'one control' inheritance control, but when I add the timer, it compiles but I don't get its functionality - and it's not ticking, as I want it to. Thanks for any help. Bernie Yaeger
7
8225
by: Jayyde | last post by:
Is there any way to accomplish this? The forms _Load event fires off several other small ones that I'd like to track time for. I can't get either the Mdi Parent form's timer _Tick event or the child form that I'm opening's _Tick to actually fire off. Any help any of you gurus can give me will be much appreciated :). -Jayyde
8
6868
by: KnighT | last post by:
I have a .net service that runs a System.Threading.Timer. The delegate points to the function that the service should execute when the timer elapses. Problem: The timer is not ticking. I have never used this timer. I used the documentation from Microsoft as a guide, but I cannot get this timer to work. Protected Overrides Sub OnStart(ByVal args() As String) Dim myTimer As New TimerState()
16
3260
by: Peter Oliphant | last post by:
Note that although this involves SAPI, it is more a question about Timers and event handlers. I wrote a Speech Recognize handler (SAPI), and put some code in it to enable a Timer. It would not do it. If I bring this same code outside this event handler, it works just fine. Is this normal?
3
3893
by: Steve | last post by:
Hi All I am using VB.net 2008 and use timer controls within my applications Question Does the code in a Timer control.tick event run on a different thread to the main Application thread (UI Thread)? In some of the timers I update some UI controls e.g statusbar.labels and I
0
9796
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9642
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10782
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10543
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10213
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7753
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
1
4422
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3972
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3078
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.