Use a Timer to change value periodically - c#

Hye there I am new to C# and just want to run a timer manually! So i just want to know what I am doing wrong in my code. I just need to display a simple message inside my timer! my code is:
public partial class Form1 : Form
{
System.Timers.Timer time;
public Form1()
{
InitializeComponent();
time = new System.Timers.Timer();
time.Interval = 10;
time.Enabled = true;
time.Start();
}
private void time_Tick(object e, EventArgs ea)
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine(i);
}
}
}
Please let me know if i am doing something wrong Thanks in advance!

You forgot to listen to the Elapsed event. Add:
time.Elapsed += new ElapsedEventHandler(time_Tick);
To the initialisation of the timer and it should call the callback function when the timer have elapsed (at the moment 10ms)
Note also that the callback function will be called every 10 ms.
Add time.Stop(); inside the callback function if you wish it to stop run.

Edited:
Maybe it is better to use class System.Windows.Forms.Timer instead of System.Timers.Timer. There you can call your function and also access your Textbox.
Otherwise you will receive an InvalidOperationException by trying to access your Textbox txt in time_Tick.
You don't neet a loop for incrementing your value i. just restart your timer and set the new value. What you are doing now is waiting ONE tick (lasting 1000 ms) and then starting your loop.
For example this could be your method:
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private int i = 0;
private Timer time;
public Form1()
{
InitializeComponent();
time = new Timer();
time.Tick += time_Tick;
time.Interval = 1000;
time.Start();
}
private void time_Tick(object e, EventArgs ea)
{
if (i < 100)
{
txt.Text = i.ToString();
i++;
time.Start();
}
}
}
}

Related

Textbox not displaying text and UI screen not moving

This is my requirement I have to use while loop inside timer, after launch application after click on button UI is locked not able to move and text is not diplaying at textbox too
below is the code
using System;
using System.Windows.Forms;
namespace WinScreenLocked
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
int Number = 0;
private void timer1_Tick(object sender, EventArgs e)
{
while (true)
{
textBox1.Text = Number.ToString();
Number++;
}
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Start();
}
}
}
// Create a 30 min timer
timer = new System.Timers.Timer(1800000);
// Hook up the Elapsed event for the timer.
timer.Elapsed += OnTimedEvent;
timer.Enabled = true;
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
// do stuff
}
with the usual caveats of: timer won't be hugely accurate and might need to GC.KeepAlive(timer)
See also: Why does a System.Timers.Timer survive GC but not System.Threading.Timer?
you can stop the thread to block the ui i.e using
System.Threading.Thread.Sleep(2000);
it takes miliseconds in above 2000 miliseconds is equal to 2 seconds.
Seeing as this is winforms you can use Application.DoEvents() to process the UI refresh.
See this : https://social.msdn.microsoft.com/Forums/en-US/b1b1969d-8a51-496c-9274-a0ac1708a8b4/what-does-applicationdoevents-actually-do?forum=csharplanguage

C# - Automatically close a form after x minutes

Situation: I wrote a WinForms application which users access via an RDP. The nature of the application is such that two users cannot run the application at the same time. The problem we're having is that folks will forget to close out of the app, essentially locking other users out.
What I'd like to do is add functionality to automatically close the app after x minutes. I realize that I need to use threading for this since marking time in the main thread would freeze up the app. I don't have a critical need to detect activity/inactivity, but if that's trivial to do, I'd definitely like to know.
Thanks in advance for any assistance!
Assuming you're talking about closing the app from inside the WinForms app itself...use a Timer as suggested by SLaks:
public partial class Form1 : Form
{
private System.Windows.Forms.Timer tmr;
public Form1()
{
InitializeComponent();
tmr = new System.Windows.Forms.Timer();
tmr.Tick += delegate {
this.Close();
};
tmr.Interval = (int)TimeSpan.FromMinutes(10).TotalMilliseconds;
tmr.Start();
}
}
If you wan't to get fancier and close after X minutes of inactivity, then write your own IMessageFilter() that resets a Timer whenever mouse/keyboard activity occurs (WM_LBUTTONDOWN, WM_KEYDOWN, WM_SYSKEYDOWN, etc.). You register your filter with Application.AddMessageFilter() in the Load() event of your Form.
This may help, just put this together, it will close the form 1.5 seconds after the button1 is pressed. you could change this to any time after form load.
public void testc()
{
Timer t = new Timer();
t.Interval = 1500;
t.Tick += new EventHandler(timer_Tick);
t.Start();
}
private void timer_Tick(object sender, EventArgs e)
{
MessageBox.Show("Tick");
this.Close();
}
private void button1_Click(object sender, EventArgs e)
{
testc();
}
I wrote a class starting from the Idle_Mind's reply, that create a message with another feature : Opacity
Add a Form to your project and call it VanishingMessage.
Add a text label to the Form, i called it : testo
Add the event PAINT to the form.
Copy and paste this code
When you call the class set the the message and seconds as parameters, like required.
I personally suggest to set the FormBorderStyle to NONE.
public partial class VanishingMessage : Form
{
private System.Windows.Forms.Timer tmr;
private System.Windows.Forms.Timer tmr2;
/// <summary>
/// Shows a message windows. 3 sec is the suggested time
/// </summary>
/// <param name="messageText">Message</param>
/// <param name="vanishingSeconds">Showing time</param>
public VanishingMessage(string messageText, int vanishingSeconds=3)
{
InitializeComponent();
double elapsedTime = 0;
testo.Text = messageText;
double vanishingMilliSeconds = vanishingSeconds * 1000;
// message dimensions
this.Width = testo.Width + 50;
this.Height = testo.Height + 50;
//text position
testo.Location = new Point((this.Width / 2) - (testo.Width / 2), (this.Height/2)-(testo.Height/2));
//first timer
tmr = new System.Windows.Forms.Timer();
tmr.Tick += delegate {
tmr.Stop();
tmr2.Stop();
tmr.Dispose();
tmr2.Dispose();
this.Close();
};
tmr.Interval = (int)TimeSpan.FromSeconds(vanishingSeconds).TotalMilliseconds;
tmr.Start();
//second timer
tmr2 = new System.Windows.Forms.Timer();
tmr2.Tick += delegate {
elapsedTime += 50;
if (elapsedTime >= (vanishingMilliSeconds * 65)/100)
this.Opacity -= 0.05f;
};
tmr2.Interval = (int)TimeSpan.FromMilliseconds(50).TotalMilliseconds;
tmr2.Start();
}
private void VanishingMessage_Paint(object sender, PaintEventArgs e)
{
Graphics g = this.CreateGraphics();
Pen p = new Pen(Color.DarkRed);
SolidBrush sb = new SolidBrush(Color.DarkRed);
Rectangle r = this.DisplayRectangle;
r.Width -= 1;
r.Height -= 1;
g.DrawRectangle(p,r);
}
}
Here how to call the class :
VanishingMessage vm = new VanishingMessage("your message",3);
vm.Show();

Only repeat a timer a limited number of times

I am trying to write an interface for a motorised stage. What I am trying to do is to create a scan feature such that the motor will move a certain distance, stop and wait a specified time and then move the same distance again. It will repeat the process until it has reached the total length specified by the user. To do this I am trying to use a Timer class features as I still want the GUI to be active during the scan.
I've got some idea of how to code it but get stuck. It would go something like:
private void btnGo_Click(object sender, EventArgs e) //On click
{
int i = 0;
int stop = 15; //number of times I want the motor to stop
System.Timers.Timer bTimer; //initialise timer
bTimer = new System.Timers.Timer(waittime); //time I want the motor to wait
bTimer.Elapsed += PerformMove;
bTimer.Enabled = true;
if(i==stop){bTimer.stop()}
}
private void PerformMove(Object source, ElapsedEventArgs e) //event to move motor
{
//movemotor
i++;
}
Not being particularly familiar with C# or timers is undoubtedly the cause of my confusion. What's the best way to approach this problem? Any example code would be great.
If somebody could clarify what the lines
bTimer.Elapsed += PerformMove;
bTimer.Enabled = true;
actually do too that would also be of great use!
EDIT (sorry, didn't think this was a key part): The value of stop is defined upon the user click of the button from a text box within the GUI. i.e.
int stop = Convert.ToDouble(tbIntervalStops.Text); //grab integer from user input upon button click
This would be the correct solution without memory leak
private int i = 0;
private int stop = 15; //number of times I want the motor to stop
private Timer bTimer; //initialise timer -> Thats wrong: nothing is INITIALIZED here its just defined
private void btnGo_Click(object sender, EventArgs e) //On click
{
i = 0;
stop = Convert.ToInt32(tbIntervalStops.Text); //using int because double is a floating point number like 12.34 and for counting only full numbers will be needed
bTimer = new System.Timers.Timer(waittime); //time I want the motor to wait + Here the Timer is INITIALIZED
bTimer.Elapsed += PerformMove; //Adds the Eventhandler, What should be called when the time is over
bTimer.Enabled = true; //This starts the timer. It enables running like pressing the start button on a stopwatch
}
private void PerformMove(Object source, ElapsedEventArgs e) //event to move motor
{
//movemotor
i++;
if (i == stop) //if stop would be a double here we will have the danger to get not a true because of rounding problems
{
bTimer.Stop();
//now enable the Garbage Collector to remove the Timer instance
bTimer.Elapsed -= PerformMove; //This removes the Eventhandler
bTimer.Dispose(); //This frees all resources held by the Timer instance.
bTimer = null;
}
}
Alternatively, you could also derive from the System.Timers.Timer object and create a wrapper which has properties specific to the task. In which case, you would simply need to instantiate a MoveTimer and subscribe to it's OnPerformMoveEvent.
Update: Added OnMovesCompletedEvent
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TimerExample
{
public class MoveTimer : System.Timers.Timer
{
public event EventHandler OnPerformMoveEvent = delegate { };
public event EventHandler OnMovesCompletedEvent = delegate { };
public MoveTimer()
{
Initialize(new TimeSpan(), 0);
}
public MoveTimer(TimeSpan wait, int moves)
{
this.Initialize(wait, moves);
}
private int _i;
private int _totalmoves;
public int Moves
{
get { return this._totalmoves; }
set { this._totalmoves = value; }
}
private TimeSpan _wait;
public TimeSpan Wait
{
get { return this._wait; }
set { this._wait = value; }
}
private System.Timers.Timer _timer;
private void Initialize(TimeSpan wait, int moves)
{
this._totalmoves = moves;
this._wait = wait;
this._timer = new System.Timers.Timer(wait.Milliseconds);
}
private void BindComponents()
{
this._timer.Elapsed += _timer_Elapsed;
}
private void UnBindComponents()
{
this._timer.Elapsed -= _timer_Elapsed;
}
public void StartTimer()
{
this._timer.Enabled = true;
}
public void StopTimer()
{
this._timer.Enabled = false;
}
void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
this._i++;
if (this.OnPerformMoveEvent != null)
this.OnPerformMoveEvent(this, EventArgs.Empty);
if (this._i == this._totalmoves)
{
this._timer.Stop();
this.UnBindComponents();
this.Dispose();
if (this.OnMovesCompletedEvent != null)
this.OnMovesCompletedEvent(this, EventArgs.Empty);
}
}
}
}
In regards to the user input where the number of moves or stops is provided as a string. I would handle this outside of the MoveTimer object. Validation should always be performed.
First determine that the value can be parsed into an integer. If not, throw an exception to let the user know that the input was entered incorrectly.
To use the above, something like the following would be all it requires:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TimerExample
{
class Program
{
static void Main(string[] args)
{
//Create move timer that will trigger 15 times, once every 30 seconds.
MoveTimer moveTimer = new MoveTimer(new TimeSpan(0, 0, 30), 15);
//Substribe to the move timer events
moveTimer.OnPerformMoveEvent += moveTimer_OnPerformMoveEvent;
moveTimer.OnMovesCompletedEvent += moveTimer_OnMovesCompletedEvent;
//Start the timer
moveTimer.StartTimer();
//What happens in between the moves performed?
}
static void moveTimer_OnMovesCompletedEvent(object sender, EventArgs e)
{
//All the moves have been performed, what would you like to happen? Eg. Beep or tell the user.
}
static void moveTimer_OnPerformMoveEvent(object sender, EventArgs e)
{
//Timer has lapsed, what needs to be done when a move is requested?
}
}
}

Can't create a timer that runs a function in C#

this time I come to you guys asking for help with Timers (System.Timers to be specific, I believe)
I need to make a timer that runs a function every second, so far this is what I've got:
public class Game1 : Microsoft.Xna.Framework.Game
{
Timer CooldownTracker;
protected override void LoadContent()
{
CooldownTracker = new Timer();
CooldownTracker.Interval = 1000;
CooldownTracker.Start();
}
private void DecreaseCooldown(List<Brick> bricks)
{
foreach (Brick brick in bricks)
{
if (brick.Cooldown == 0)
brick.Cooldown = 2;
else
brick.Cooldown--;
}
}
}
...How do I make the timer run the DecreasedCooldown(List bricks) function? I've tried with Timer.Elapsed but I get nothing, I can't pass down the arguments that way. Any ideas?
Thanks!
You need to attach a Timer Elapsed event like:
CooldownTracker = new Timer();
CooldownTracker.Elapsed += CooldownTracker_Elapsed; //HERE
CooldownTracker.Interval = 1000;
CooldownTracker.Start();
and then the event:
void CooldownTracker_Elapsed(object sender, ElapsedEventArgs e)
{
DecreaseCooldown(yourList);
}
You can use Thread if you want. It's not so accurate maybe cause of ThreadPool but can help.
Like
private bool run = true;
Thread timer = new Thread(Run);
timer.Start();
And define Run
private void Run()
{
while(run)
{
// Call function
Thread.Sleep(1000); //Time in millis
}
}
if you get cross-thread exception try to use for loop instead of foreach or lock your resources.

C# Simple Countdown - What am I doing wrong?

I wanted to make a simple Countdown-Application with C# to show as an example.
For the very first and basic version I use a Label to display the current time left in seconds and a Button to start the countdown. The Button's Click-Event is implemented like this:
private void ButtonStart_Click(object sender, RoutedEventArgs e)
{
_time = 60;
while (_time > 0)
{
_time--;
this.labelTime.Content = _time + "s";
System.Threading.Thread.Sleep(1000);
}
}
Now when the user clicks the Button the time is actually counted down (as the application freezes (due to Sleep())) for the chosen amount of time but the Label's context is not refreshed.
Am I doing something generally wrong (when it comes to Threads) or is it just a problem with the UI?
Thank you for your answers!
I now use a System.Windows.Threading.DispatcherTimer to do as you told me. Everything works fine so this question is officially answered ;)
For those who are interested: Here is my code (the essential parts)
public partial class WindowCountdown : Window
{
private int _time;
private DispatcherTimer _countdownTimer;
public WindowCountdown()
{
InitializeComponent();
_countdownTimer = new DispatcherTimer();
_countdownTimer.Interval = new TimeSpan(0,0,1);
_countdownTimer.Tick += new EventHandler(CountdownTimerStep);
}
private void ButtonStart_Click(object sender, RoutedEventArgs e)
{
_time = 10;
_countdownTimer.Start();
}
private void CountdownTimerStep(object sender, EventArgs e)
{
if (_time > 0)
{
_time--;
this.labelTime.Content = _time + "s";
}
else
_countdownTimer.Stop();
}
}
Yes, event handlers should not block - they should return immediately.
You should implement this by a Timer, BackgroundWorker or Thread (in this order of preference).
What you are seeing is the effect of a long-running message blocking the windows message queue/pump - which you more commonly associate with the white application screen and "not responding". Basically, if your thread is sleeping, it isn't responding to messages like "paint yourself". You need to make your change and yield control to the pump.
There are various ways of doing this (ripper234 does a good job of listing them). The bad way you'll often see is:
{ // your count/sleep loop
// bad code - don't do this:
Application.DoEvents();
System.Threading.Thread.Sleep(1000);
}
I mention this only to highlight what not to do; this causes a lot of problems with "re-entrancy" and general code management. A better way is simply to use a Timer, or for more complex code, a BackgroundWorker. Something like:
using System;
using System.Windows.Forms;
class MyForm : Form {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.Run(new MyForm());
}
Timer timer;
MyForm() {
timer = new Timer();
count = 10;
timer.Interval = 1000;
timer.Tick += timer_Tick;
timer.Start();
}
protected override void Dispose(bool disposing) {
if (disposing) {
timer.Dispose();
}
base.Dispose(disposing);
}
int count;
void timer_Tick(object sender, EventArgs e) {
Text = "Wait for " + count + " seconds...";
count--;
if (count == 0)
{
timer.Stop();
}
}
}

Categories

Resources