I'm trying to make a simple countdown timer program. There are two timer objects. Once timer1 runs out of time, it stops and timer2 starts counting down. When timer2 runs out of time, timer1 starts again and so on. Here is my code:
private void timer1_Tick(object sender, EventArgs e)
{
milli1--;
if(milli1 == -1)
{
sec1--;
milli1 = 59;
if (sec1 == -1)
{
min1--;
sec1 = 59;
if (min1 == -1)
{
min1 = 0;
sec1 = 0;
milli1 = 0;
Console.WriteLine("Timer1 stops!");
timer1.Stop();
timer2.Start();
}
}
}
//updates displayed time
}
However, when timer1 stops, timer2 doesn't seem to start. Somehow, timer1 continues ticking and continuously outputs "Timer1 Stops!" to console. How do I fix this?
EDIT: Here is my timer2_Tick():
private void timer2_Tick(object sender, EventArgs e)
{
milli2--;
if (milli2 == -1)
{
sec2--;
milli2 = 59;
if (sec2 == -1)
{
min2--;
sec2 = 59;
if (min2 == -1)
{
min2 = 0;
sec2 = 0;
milli2 = 0;
timer2.Stop();
timer1.Start();
}
}
}
//updates displayed time
}
EDIT 2: Two timers with same interval is a trivial matter. My code also doesn't work when the timers have different intervals.
I am not sure why you want to use a Timer for a console application as it is not event driven as a Windows.Forms.Timer is. You may be using a Threading timer but your code won’t work as it is using this timer. So below I created a windows form application and set the output type to the console and used the timers as you described and it works as expected. I do not think you can use a timer the way you are in a console application. Again this code makes little sense as ONE timer will do the same thing. If you must use a console application then you may want to check the following post: How do you add a timer to a C# console application
int milli1 = 0;
int milli2 = 0;
int sec1 = 0;
int min1 = 0;
int sec2 = 0;
int min2 = 0;
public Form1() {
InitializeComponent();
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e) {
Console.WriteLine("Timer1 tick!");
milli1--;
if (milli1 == -1) {
sec1--;
milli1 = 59;
if (sec1 == -1) {
min1--;
sec1 = 59;
if (min1 == -1) {
min1 = 0;
sec1 = 0;
milli1 = 0;
//Console.WriteLine("Timer1 stops!");
timer1.Stop();
timer2.Start();
}
}
}
//updates displayed time
}
private void timer2_Tick(object sender, EventArgs e) {
Console.WriteLine("Timer2 tick!");
milli2--;
if (milli2 == -1) {
sec2--;
milli2 = 59;
if (sec2 == -1) {
min2--;
sec2 = 59;
if (min2 == -1) {
min2 = 0;
sec2 = 0;
milli2 = 0;
timer2.Stop();
timer1.Start();
}
}
}
//updates displayed time
}
}
Related
In a Winforms application, there are 3 different numericupdown such as min, sec, millisecond. How do I make a timer that counts down the value of entering numericupdowns? I have tried with if else blocks. I also saw a lot of time timespawn titles on the internet. Which is better for this countdown? if else blocks or timespawn
numericUpDownMiliSn.Value--;
if (numericUpDownMiliSn.Value == 0)
{
if (numericUpDownMiliSn.Value == 0 && numericUpDownSn.Value == 0 && numericUpDownDk.Value == 0)
{
timer2.Stop();
button2.Text = "Baslat";
durum = false;
}
else
{
if (numericUpDownSn.Value > 0)
{
numericUpDownSn.Value--;
numericUpDownMiliSn.Value = 60;
}
else
{
numericUpDownMiliSn.Value = 60;
}
if (numericUpDownSn.Value > 0)
{
numericUpDownSn.Value--;
numericUpDownSn.Value = 60;
}
}
}
From my comments in the original question above:
Timers in WinForms are NOT accurate, so you shouldn't be basing your
time off incrementing/decrementing those in a Tick() event. You should
definitely be using a TimeSpan (derived from subtracting the current
time from some future target time; based on the initial values in your
NumericUpDowns)...then simply update the NumericUpDowns with the
numbers in the TimeSpan.
Here's how that code might look:
private DateTime targetDT;
private void button1_Click(object sender, EventArgs e)
{
TimeSpan ts = new TimeSpan(0, 0, (int)numericUpDownMn.Value, (int)numericUpDownSn.Value, (int)numericUpDownMiliSn.Value);
if (ts.TotalMilliseconds > 0)
{
button1.Enabled = false;
numericUpDownMn.Enabled = false;
numericUpDownSn.Enabled = false;
numericUpDownMiliSn.Enabled = false;
targetDT = DateTime.Now.Add(ts);
timer1.Start();
}
}
private void timer1_Tick(object sender, EventArgs e)
{
TimeSpan ts = targetDT.Subtract(DateTime.Now);
if (ts.TotalMilliseconds > 0)
{
numericUpDownMn.Value = ts.Minutes;
numericUpDownSn.Value = ts.Seconds;
numericUpDownMiliSn.Value = ts.Milliseconds;
}
else
{
timer1.Stop();
numericUpDownMn.Value = 0;
numericUpDownSn.Value = 0;
numericUpDownMiliSn.Value = 0;
button1.Enabled = true;
numericUpDownMn.Enabled = true;
numericUpDownSn.Enabled = true;
numericUpDownMiliSn.Enabled = true;
}
}
Im creating a transition for my form in Visual Studio,
i'm coding a slide effect for the width but it ends up to slow
is there anyway to make it more faster?
btw here is the code :
`int check = 0;
private void button1_Click(object sender, EventArgs e)
{
this.button1.Text = "Hide";
if (check == 0)
{
for (int i = 350; i <= 824; ++i)
{
this.Size = new Size(i, 507);
Thread.Sleep(10);
this.CenterToScreen();
}
check = 1;
}
else if (check == 1)
{
this.button1.Text = "Key";
for (int i = 824; i >= 351; i--)
{
this.Size = new Size(i, 507);
Thread.Sleep(5);
this.CenterToScreen();
}
check = 0;
}
}
By using your existing code, you can tune it for the sake of speed like;
private int check = 0;
private void button1_Click(object sender, EventArgs e)
{
this.button1.Text = "Hide";
if (check == 0)
{
for (int i = 350; i <= 824; i += 2)
{
this.Size = new Size(i, 507);
Thread.Sleep(1);
this.CenterToScreen();
}
check = 1;
}
else if (check == 1)
{
this.button1.Text = "Key";
for (int i = 824; i >= 351; i -= 2)
{
this.Size = new Size(i, 507);
Thread.Sleep(1);
this.CenterToScreen();
}
check = 0;
}
}
You can change Thread.Sleep lines as above and increase or decrease the loop variables for faster an animation.
The problem is the label gets displayed before the progress-bar is completed. How do I make the label display only after the progress-bar is fully complete?
I tried changing the max values to a higher number but it didn't work.
public partial class dload : Form
{
public dload()
{
InitializeComponent();
}
private void dload_Load(object sender, EventArgs e)
{
label1.Visible = false;
}
private void button1_Click(object sender, EventArgs e)
{
int i = 0;
progressBar1.Minimum = 0;
progressBar1.Maximum = 5000;
for (i = 0; i <= 5000; i++)
{
progressBar1.Value = i;
if (i == 5000)
{
label1.Visible = true;
}
}
}
}
Actually, Your code run very vast, it is about less than a second to set value from 0% to 100% ! But
ProgressBar has two styles for displaying the current status (Classic and Continues).
In Continues mode if the progress value went to 100% from 0% the control will show an animation, which is not display the real and accurate progress. You can set a delay via Thread.Sleep() and show your label immediately after the for loop to find out to what i happening !
The Below code will work:
private void button1_Click(object sender, EventArgs e)
{
int i = 0;
progressBar1.Minimum = 0;
progressBar1.Maximum = 5000;
for (i = 0; i <= 5000; i++)
{
Thread.Sleep(1);
progressBar1.Value = i;
}
label1.Visible = true;
}
This is an animation problem. A "hack" around it is to actually decrease the progress value by 1:
progressBar1.Minimum = 0;
progressBar1.Maximum = 5000;
for (int i = 0; i < progressBar1.Maximum; i++) {
progressBar1.Value = i;
progressBar1.Value = Math.Max(i - 1, progressBar1.Minimum);
}
label1.Visible = true;
use progressBar1.Refresh:
public partial class dload : Form
{
public dload()
{
InitializeComponent();
}
private void dload_Load(object sender, EventArgs e)
{
label1.Visible = false;
}
private void button1_Click(object sender, EventArgs e)
{
int i = 0;
progressBar1.Minimum = 0;
progressBar1.Maximum = 5000;
for (i = 0; i <= 5000; i++)
{
progressBar1.Value = i;
progressBar1.Refresh();
if (i == 5000)
{
label1.Visible = true;
}
}
}
I'm trying to make a Tamagochi but I've ran into a problem. I have a Progressbar with a max value of 300. Every 5-8 seconds the Progressbar empties a bit. Once it gets below 250 you're allowed to sleep.
Here is the code i have so far:
private void BtnSleep_Click(object sender, EventArgs e)
{
if (PgbSleep.Value <= 250)
{
int temp = PgbSleep.Maximum - PgbSleep.Value;
if (temp + PgbSleep.Value >= 300)
{
Timer2.Stop();
Thread.Sleep(20000);
PgbSleep.Value = 300;
Timer2.Start();
}
}
else
{
MessageBox.Show("Your pokemon is not tired enough to sleep! try playing with it");
}
}
I'm trying to find a replacement for the
Thread.Sleep(20000);
But dont know what to use. Any help would be much appreciated!
The
Thread.Sleep(20000);
Is supposed to be a cooldown, once its completed the user is allowed to sleep again if the requirements are met.
Try using a timer:
Timer sleepTimer = new Timer(20000); //Creates a timer for sleeping
public MyClass()
{
sleepTimer.Elapsed += new EventHandler((s, e) => WakeUp());
}
private void BtnSleep_Click(object sender, EventArgs e)
{
if (PgbSleep.Value <= 250)
{
int temp = PgbSleep.Maximum - PgbSleep.Value;
if (temp + PgbSleep.Value >= 300)
{
Timer2.Stop();
sleepTimer.Start();
}
}
else
{
MessageBox.Show("Your pokemon is not tired enough to sleep! try playing with it");
}
}
private void WakeUp()
{
PgbSleep.Value = 300;
Timer2.Start();
}
I have created a video which explains my problem. In text form - My Main form is crashing when the timer is run and i'm not sure why, the application keeps running, even though the main form seems to have crashed.
namespace ItunesGamesEqualiser
{
public partial class GUI : Form
{
private void refreshBar_Scroll(object sender, EventArgs e)
{
timer1.Interval = prbLevel.Value;
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
AudioSessionControl session;
AudioSessionControl itunesSession;
MMDeviceEnumerator DevEnum = new MMDeviceEnumerator();
MMDevice device = DevEnum.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);
// Note the AudioSession manager did not have a method to enumerate all sessions in windows Vista
// this will only work on Win7 and newer.
for (int i = 0; i < device.AudioSessionManager.Sessions.Count; i++)
{
itunesSession = device.AudioSessionManager.Sessions[i];
if (itunesSession.SessionIdentifier.Contains("iTunes") == true) //find itunes audio service
{
for (int j = 0; j < device.AudioSessionManager.Sessions.Count; j++)
{
session = device.AudioSessionManager.Sessions[j];
if (session.SessionIdentifier.Contains("iTunes") == false) //find game audio service
{
if (session.State == AudioSessionState.AudioSessionStateActive)
{
Process p = Process.GetProcessById((int)session.ProcessID);
Console.WriteLine("ProcessName: {0}", p.ProcessName);
AudioMeterInformation mi = session.AudioMeterInformation;
AudioMeterInformation imi = itunesSession.AudioMeterInformation;
SimpleAudioVolume vol = session.SimpleAudioVolume;
SimpleAudioVolume ivol = itunesSession.SimpleAudioVolume;
//int start = Console.CursorTop;
ivol.MasterVolume = 1;
float origVol = ivol.MasterVolume;
while (true)
{
//Draw a VU meter
int len = (int)(mi.MasterPeakValue * 79);
int ilen = (int)(imi.MasterPeakValue * 79);
//Console.SetCursorPosition(0, start);
//Game Meter
if (len > 30)
{
float curvol = origVol - (0.1f * (len - 10) / 10);
if (curvol < 0) curvol = 0;
ivol.MasterVolume = curvol;
prbLevel.Value = len;
}
else
{
ivol.MasterVolume = origVol;
//Console.WriteLine("null");
}
}
}
}
}
}
}
//If we end up here there where no open audio sessions to monitor.
lblName.Text = "No game found, please start game and iTunes";
}
private void btnStop_Click(object sender, EventArgs e)
{
timer1.Stop();
}
}
}
Application crashes because of your code in timer tick event. App continues running even after crashing because the timer is not disabled or disposed. Timer class requests GC not to collect using - GCHandle.Alloc, when you set timer.Enabled = true. So even after timer object reference goes not-reachable it will not be garbage collected. Fix the problem in your timer tick event and dipose the timer properly.