473,395 Members | 2,253 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

C# Timer tick inaccurate with progressbar

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.Tick 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.Timer called PlayerTimer and a progressbar called playerProgressbar.
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_Tick 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 progressbarvalue to 0, show the attack button again and calculate the time this has taken.

The reason I added this "PlayerTimer.Tick += new EventHandler(PlayerTimer_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.Timer, and still not accurate.

Ask if something is unclear.

Thanks in advanced :)

Marius
Mar 4 '08 #1
9 7265
shweta123
692 Expert 512MB
Hi,

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

1) progressBar1.Maximum
2) progressBar1.Minimum
3) progressBar1.Step
4) progressBar1.Value

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.Interval = 100;
playerProgressbar.Maximum = 50;
playerProgressbar.Minimum= 0;
playerProgressbar.Value= 0;

startTime = DateTime.Now;
PlayerTimer.Enabled = true;
PlayerTimer.Start()
}

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

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

private void PlayerTimer_Tick(object sender, EventArgs e)
{
playerProgressbar.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.Tick 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.Timer called PlayerTimer and a progressbar called playerProgressbar.
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_Tick 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 progressbarvalue to 0, show the attack button again and calculate the time this has taken.

The reason I added this "PlayerTimer.Tick += new EventHandler(PlayerTimer_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.Timer, and still not accurate.

Ask if something is unclear.

Thanks in advanced :)

Marius
Mar 4 '08 #2
Hi

Thanks for quick response.

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


I've tried both: playerProgressbar.increment(1); and
playerProgressbar.Value += 1;
playerProgressbar.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.Maximum
2) progressBar1.Minimum
3) progressBar1.Step
4) progressBar1.Value

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.Interval = 100;
playerProgressbar.Maximum = 50;
playerProgressbar.Minimum= 0;
playerProgressbar.Value= 0;

startTime = DateTime.Now;
PlayerTimer.Enabled = true;
PlayerTimer.Start()
}

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

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

private void PlayerTimer_Tick(object sender, EventArgs e)
{
playerProgressbar.value +=1;
.................
}
Mar 4 '08 #3
shweta123
692 Expert 512MB
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_Tick() procedure you might get the correct result.

e.g.

private void PlayerTimer_Tick(object sender, EventArgs e)
{
if(startTime == "")
{
//set the startTime value here when timer starts
startTime = DateTime.Now;
}
playerProgressbar.Increment(1);
if (playerProgressbar.Value >= playerProgressbar.Maximum)
{
PlayerTimer.Stop();
PlayerTimer.Enabled = false;
playerProgressbar.Value = 0;
playerattackBtn.Visible = true;
stopTime = DateTime.Now;
TimeSpan time = stopTime.Subtract(startTime);
MessageBox.Show(Convert.ToString(time));
}
}




Hi

Thanks for quick response.

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


I've tried both: playerProgressbar.increment(1); and
playerProgressbar.Value += 1;
playerProgressbar.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
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_Tick() procedure you might get the correct result.

e.g.

private void PlayerTimer_Tick(object sender, EventArgs e)
{
if(startTime == "")
{
//set the startTime value here when timer starts
startTime = DateTime.Now;
}
playerProgressbar.Increment(1);
if (playerProgressbar.Value >= playerProgressbar.Maximum)
{
PlayerTimer.Stop();
PlayerTimer.Enabled = false;
playerProgressbar.Value = 0;
playerattackBtn.Visible = true;
stopTime = DateTime.Now;
TimeSpan time = stopTime.Subtract(startTime);
MessageBox.Show(Convert.ToString(time));
}
}
Mar 4 '08 #5
Plater
7,872 Expert 4TB
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
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 Expert 512MB
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.maximum. Instead of this you can compare it using progressbar value = progressbar.maximum

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
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=continuous 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.maximum. Instead of this you can compare it using progressbar value = progressbar.maximum
Mar 5 '08 #9
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=continuous 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
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...
14
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...
7
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...
10
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...
2
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...
7
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...
8
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...
16
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...
3
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...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
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,...
0
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...
0
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...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

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.