Timer in C# is acting very strangely - c#

I'm unsure of what's wrong with this code. The timer1 interval is set to 1000.
namespace timerbug
{
public partial class Form1 : Form
{
int value;
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
do
{
value++;
label1.Text = value.ToString();
}
while (value <= 5);
}
private void button1_Click(object sender, EventArgs e)
{
value = 0;
timer1.Start();
}
}
}
I thought the label would display 1 to 5, then stop. The counting doesn't even show up until 6, and continues to go up until I stop the program. Can someone explain why the numbers 1 to 5 are not showing up, and then why it doesn't stop at 5? Thank you.

As other people have correctly pointed out in comments, it stops at 6 instead of 5 because 6 is the first value for which value <= 5 evaluates as false (You are using a do-while loop, which means the condition is evaluated after the body is executed.). In order to stop at 5, you could either use regular while loop or change the condition to value < 5 or value <= 4.
Furthermore, 6 iterations of a loop in C# happen in a few microseconds. You could not really see the numbers being displayed in the label even if everything else was done correctly, simply because it would happen too fast. In order to see anything happen, you would need to introduce some kind of a delay (Thread.Sleep()) and at the end of each iteration, you would have to call Application.DoEvents() to let the Form re-paint.
Alternatively, you could use the Timer's ticks, which would be preferable in most cases. You could do it like this for instance.
namespace timerbug
{
public partial class Form1 : Form
{
int value;
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
if (value < 5)
{
value++;
label1.Text = value.ToString();
}
else
{
timer1.Stop();
}
}
private void button1_Click(object sender, EventArgs e)
{
value = 0;
timer1.Start();
}
}
}

Changing the timer1_tick code to this worked fine, thanks for the assistance. I have a lot to learn.
value++;
if (value >= 5)
{
timer1.Stop();
}
label1.Text = value.ToString();
label1.Invalidate();
label1.Update();
}

Related

increment by 2 instead of 1 after button is clicked

This is my code
int Moneycount;
private void mButton_Click(object sender, EventArgs e)
{
Moneycount++;
MoneyCount.Text = Moneycount.ToString();
}
private void level1_Click(object sender, EventArgs e)
{
}
"mButton" is incremented by 1 every time I press it,
so I want it to be incremented by 2 instead of 1 after I press "level1"
So if I understand you correctly, you want mButton to increment MoneyCount by one every time you press it. But after pressing level1, mButton should increment by 2 instead.
Try this:
int Moneycount;
int amountToIncrement = 1;
private void mButton_Click(object sender, EventArgs e)
{
Moneycount += amountToIncrement;
MoneyCount.Text = Moneycount.ToString();
}
private void level1_Click(object sender, EventArgs e)
{
amountToIncrement = 2;
}
Instead of level1 being an actual Button, it might be useful to make it a Checkbox instead, and then make it look like a button by setting the Appearance property to Button in the designer. Here is a simple example where clicking on mButton looks at the Checked state of level1 to determine the correct increment value. At the same time, toggling the checked state of level1 sets the Increment value of the NumericUpDown control so that the Up/Down arrows also use the correct value of 1 or 2.
Example of coding the MainForm that has the behavior you describe:
public partial class MainForm : Form , INotifyPropertyChanged
{
public MainForm()
{
InitializeComponent();
level1.Appearance = Appearance.Button;
numericUpDown.DataBindings.Add(
nameof(NumericUpDown.Value),
this,
nameof(Moneycount),
false,
DataSourceUpdateMode.OnPropertyChanged);
}
private void mButton_Click(object sender, EventArgs e)
{
Moneycount += level1.Checked ? 2 : 1;
}
private void level1_CheckedChanged(object sender, EventArgs e)
{
// Clicking up/down arrows increments 1 or 2
numericUpDown.Increment = level1.Checked ? 2 : 1;
}
public int Moneycount
{
get => _moneyCount;
set
{
if(!Equals(_moneyCount, value))
{
_moneyCount = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Moneycount)));
}
}
}
int _moneyCount = 0;
public event PropertyChangedEventHandler PropertyChanged;
}
Try
Moneycount += 2;
this increments by two

Taking Value From Text Box Into Total (VS - C#)

I am new to the C# scene, so don't really have much knowledge - This is my first project.
I am looking to create a very basic calorie counter, which eventually will include other functions.
Here's what I have so far;
I want to know how to take the value from the text box on the click of the 'Add' button - Which adds to the total value (bottom right)
I'm looking for any tips/videos to help so anything is appreciated.
TIA
I made a simple implementation for you, you could refer to it:
using System;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
bool Flag = Int32.TryParse(textBox1.Text, out int result);//Determine if it is a number
if (textBox1.Text == "")//If it is null, falg takes true and skips the next judgment
{ Flag = true; }
else if (!Flag)
{
MessageBox.Show("Input Error");
textBox1.Text = null;
}
}
private void button1_Click(object sender, EventArgs e)
{
Int32.TryParse(textBox1.Text, out int result);
int total =result + Convert.ToInt32(label3.Text);
label3.Text = total.ToString();
}
private void button2_Click(object sender, EventArgs e)
{
label3.Text = "0";
}
}
}

setText in textbox with infinite loop

I am writing activity recognition software in realtime. But i can't setText in textbox with infinite loop. I try to search Google but no answer. When, i using "textbox.Text += "ZZZZ", it working but I using "textbox.Text = "ZZZ" ", it not working. I hope someone can point me how to solve
private void button1_Click(object sender, EventArgs e)
{
for (; ; ){
Thread.Sleep(20);
........process....
tb_activity = "AAA";
}
}
You can use the new await and async feature in .Net:
private void button1_Click(object sender, EventArgs e)
{
EndlessTask();
}
async Task EndlessTask()
{
for(int i = 0; true; i++)
{
textBox1.Text = i.ToString();
await Task.Delay(500);
}
}
[Edit] Note, if you want to get rid of the async warning:
#pragma warning disable 4014
EndlessTask();
#pragma warning restore 4014
i can't setText in textbox with infinite loop
you can never confirm that un till unless you debug your application while using the Thread.Sleep() in infinite loop.
Reason: when you use Thread.Sleep() it makes your Main thread to sleep so it is not a good practice to use Thread.Sleep() . it hangs your UI therefore you can not see the Control Updates on the UI like Label Text update ,TextBox Text Update things like that.
ofcourse you call Application.DoEvents() to refresh the UI but it is not a good practice as there are many other problems.
Solution: i suggest you to use Timer instead of using Thread.Sleep() as it runs in the background so it doesnot hang your UI and also you can see the updates on UI.
Simple Example to show you how to use Timer for updating the Text on Textbox # certain intervals
public partial class Form1 : Form
{
int count = 0;
string text1 = "this is a scrolling text";
System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
textBox1.ReadOnly = true;
SetTimer(500);
}
private void SetTimer(int milliseconds)
{
timer1.Tick+=new EventHandler(timer1_Tick);
timer1.Interval = milliseconds;
timer1.Start();
}
private void timer1_Tick(Object o, EventArgs e)
{
if (count < text1.Length)
{
textBox1.Text += text1[count];
count++;
}
else
{
timer1.Stop();
button1.Enabled = true;
textBox1.ReadOnly = false;
}
}
}

How to use same timer for different time intervals?

I am using a timer in my code. Status bar updates in tick event on clicking respective button for the time inteval mentioned in properties say one second. Now i want to use the same timer for a different time interval say two seconds for a different oepration. How to achieve that?
Create a second timer. There is nothing to gain from hacking the first timer.
As #Henk noted, Timers are not that expensive. (Especially not compared to fixing hard to maintain code!)
I agree with #Henk and others.
But still, something like this could work:
Example
Int32 counter = 0;
private void timer1_Tick(object sender, EventArgs e)
{
if (counter % 1 == 0)
{
OnOneSecond();
}
if (counter % 2 == 0)
{
OnTwoSecond();
})
counter++;
}
Updated Example
private void Form_Load()
{
timer1.Interval = 1000; // 1 second
timer1.Start(); // This will raise Tick event after 1 second
OnTick(); // So, call Tick event explicitly when we start timer
}
Int32 counter = 0;
private void timer1_Tick(object sender, EventArgs e)
{
OnTick();
}
private void OnTick()
{
if (counter % 1 == 0)
{
OnOneSecond();
}
if (counter % 2 == 0)
{
OnTwoSecond();
}
counter++;
}
Change timer Interval property.
Change the Interval property in every elapsed time. for example, this program process data 30 seconds and sleep 10 seconds.
static class Program
{
private System.Timers.Timer _sleepTimer;
private bool _isSleeping = false;
private int _processTime;
private int _noProcessTime;
static void Main()
{
_processTime = 30000; //30 seconds
_noProcessTime = 10000; //10 seconds
this._sleepTimer = new System.Timers.Timer();
this._sleepTimer.Interval = _processTime;
this._sleepTimer.Elapsed += new System.Timers.ElapsedEventHandler(sleepTimer_Elapsed);
ProcessTimer();
this._sleepTimer.Start();
}
private void sleepTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
ProcessTimer();
}
private void ProcessTimer()
{
_sleepTimer.Enabled = false;
_isSleeping = !_isSleeping;
if (_isSleeping)
{
_sleepTimer.Interval = _processTime;
//process data HERE on new thread;
}
else
{
_sleepTimer.Interval = _noProcessTime;
//wait fired thread and sleep
Task.WaitAll(this.Tasks.ToArray());
}
_sleepTimer.Enabled = true;
}
}

Timer intervals, Making 1 timer stop another timer -

Hey guys im trying to get a simple button masher up, What i want timer1 to do is mash keys in richtextbox1 for 30 seconds over and over, after 30 seconds Activate timer2, which will disable timer 1 and press keys in richtextbox 2 once, then wait 10 seconds and activate timer 1 again.
Im extremley new to c# but ive tried using timer 3 to stop timer 2 and start timer 1 again and it just messes it self up. The code ive tried is below. Any help apreciated...
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;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
SendKeys.Send(richTextBox1.Text);
SendKeys.Send("{ENTER}");
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
timer2.Enabled = true;
}
private void timer2_Tick(object sender, EventArgs e)
{
SendKeys.Send(richTextBox2.Text);
SendKeys.Send("{ENTER}");
timer1.Enabled = false;
}
private void timer3_Tick(object sender, EventArgs e)
{
timer1.Enabled = true;
timer2.Enabled = false;
}
private void richTextBox2_TextChanged(object sender, EventArgs e)
{
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
}
}
}
I suggest to use just one timer, increment a state counter every second, and perform an action base on the current state.
public Form1()
{
this.InitializeComponent();
// Just to illustrate - can be done in the designer.
this.timer.Interval = 1000; // One second.
this.timer.Enable = true;
}
private Int32 state = 0;
private void timer_Tick(Object sender, EventArgs e)
{
if ((0 <= this.state) && (this.state < 30)) // Hit text box 1 30 times.
{
SendKeys.Send(this.richTextBox1.Text);
SendKeys.Send("{ENTER}");
}
else if (this.state == 30) // Hit text box 2 once.
{
SendKeys.Send(this.richTextBox2.Text);
SendKeys.Send("{ENTER}");
}
else if ((31 <= this.state) && (this.state < 40)) // Do nothing 9 times.
{
// Do nothing.
}
else
{
throw new InvalidOperationException(); // Unexpected state.
}
// Update state.
this.state = (this.state + 1) % 40;
}
The variant with two numeric up down controls.
public Form1()
{
this.InitializeComponent();
// Just to illustrate - can be done in the designer.
this.timer.Interval = 1000; // One second.
this.timer.Enable = true;
}
private Int32 state = 0;
private void timer_Tick(Object sender, EventArgs e)
{
Decimal n1 = this.numericUpDown1.Value;
Decimal n2 = this.numericUpDown2.Value;
if ((0 <= this.state) && (this.state < n1))
{
SendKeys.Send(this.richTextBox1.Text);
SendKeys.Send("{ENTER}");
}
else if (this.state == n1)
{
SendKeys.Send(this.richTextBox2.Text);
SendKeys.Send("{ENTER}");
}
else if ((n1 <= this.state) && (this.state < n1 + n2))
{
// Do nothing.
}
else
{
// Reset state to resolve race conditions.
this.state = 0;
}
// Update state.
this.state = (this.state + 1) % (n1 + n2);
}
If timer3 is running continuously, won't it start timer1 and stop timer2 at unpredictable times, without warning?
IOW, what starts and stops timer3?
As JustLoren pointed out, there might be a cleaner way to do this. Perhaps a single timer event and some controlling logic and flags, rather than trying to juggle three timers.

Categories

Resources