I used the following line of code
int pp = DateTime.Now.Hour;
and it is ok. I wrote
label1.text=pp.tostring();
for verification and it works, but if I open my form at 19:59 (eg.) in label1 appears 19 and after one minute, when the clock is 08:00, the value in label1 is not changing and still appears 19, not 20.
After that, if I close the form and reopen it, the number in label1 is 20.
How can I modify the value from datetime.now.hour in real time, while the form is running?
thank you
Since you are using the "form" terminology, I'll assume Windows Forms, and the easiest way would be adding a Timer component, set a reasonable Interval (reasonable meaning how long is it the maximum you can afford to delay when the hour changes before the label changes... the higher the interval, the less CPU your process will occupy) on it, and on its Tick event, do your:
static void MyTimer_Tick(object sender, EventArgs e)
{
int pp = DateTime.Now.Hour;
label1.text=pp.tostring();
}
You need to implement a Timer, and have its Elapsed event update label1.text. Simply calling DateTime.Now.Hour is not enough, as that only updates it once. It does not set a recurring method to constantly update.
using System.Timers;
namespace Example {
static Timer _timer;
static void Main() {
_timer = new Timer(1000); // Update every 1 second.
_timer.Elapsed += UpdateMyLabel;
_timer.Start();
}
static void UpdateMyLabel(object sender, ElapsedEventArgs e) {
label1.Text = DateTime.Now.Hour;
}
}
I would deduce the Label class and use timer tick for updating the label. Just like in OOP ;)
Related
my school project is to make a c# aplication with one button start/stop that starts to count the time and by clicking again stops count the time.
When i use this 3 lines
txtVrijeme.Text = Convert.ToString(sada.AddSeconds(i).ToString("HH:mm:ss"));
Thread.Sleep(1000);
i++;
without loop (while,for,goto etc.) in forms apk. it works (display 00:00:00, and if i click again 00:00:01) but when I use loop it does not display anything. Why ? btw. console aplication works with this code without any problem(loop in console)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace BradičićManuelŠtoperica
{
public partial class Form1 : Form
{
DateTime sada = new DateTime(2009, 6, 22, 0, 0, 0);
int i = 0;
bool x = true;
public Form1()
{
InitializeComponent();
}
void execute(bool y)
{
while (y == true)
{
txtVrijeme.Text = Convert.ToString(sada.AddSeconds(i).ToString("HH:mm:ss"));
Thread.Sleep(1000);
i++;
}
}
private void btnStartStop_Click(object sender, EventArgs e)
{
if (x == false)
x = true;
else
x = false;
execute(x);
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
}
}
excuse my English :)
Changing a textbox property does not directly draw anything to the screen.
Say it again:
Changing a textbox property does not directly draw anything to the screen.
What does happen is the Textbox control will invalidate it's graphics area, which will cause a WM_PAINT message to be generated.
The program needs to process this WM_PAINT message before the screen can be updated. The thread that receives and processes your paint events is the same thread where your execute() method is running. It's also the same thread that would handle your btnStartStop_Click() method.
Unfortunately, the execute() method never finishes. It never lets execution on that thread fall back to your program's main message loop, so your program can't repaint the textbox and it can't handle the button click that might finally let the execute() method stop. Even when it pauses, it puts the whole thread to sleep.
What you need to do instead is use a Timer component, and handle the Timer's Tick event.
Additionally, timer events are not perfectly precise. The slight variance for each Tick event can add up over time, so rather than incrementing the current value for each event your program should remember the start time and compute the difference from the current time.
As others have said, part of the problem is that you're trying to execute a hard loop inside the same thread that's responsible for updating the UI. Instead of using a loop like this, it's better to use a Timer, because the timer will run in a different thread so your UI will remain responsive.
The Timer has an Interval property that defines how often it executes a task. In our case it will be updating the textbox text. I've set this value to 100 milliseconds in the code below. The timer also has a Tick event that will execute every time the Interval elapses. Inside this event is where we put the code to update the textbox text.
We should should use a Stopwatch to measure elapsed time, because that's what it was built for. The DateTime object is great for holding dates, but it's not as accurate for measuring time.
A stopwatch has a Start and a Stop method that we can call from the button click event, so inside that event all we have to do is first check if the stopwatch is running. If it is, then we Stop it. If it isn't, then we Start it.
Putting these ideas together, your code could look something like this:
// At the top of your file, you'll need this to access the Timer:
using System.Windows.Forms;
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private static Stopwatch stopwatch = new Stopwatch();
private static readonly Timer Timer = new Timer { Interval = 100 };
private void Form1_Load(object sender, EventArgs e)
{
btnStartStop.Text = "Start";
txtVrijeme.Text = stopwatch.Elapsed.ToString("hh\\:mm\\:ss\\.ff");
Timer.Tick += Timer_Tick; // This hooks up an event handler for the Tick event
}
// This code executes every {Timer.Interval} millisecond when the timer is running
private void Timer_Tick(object sender, EventArgs e)
{
txtVrijeme.Text = stopwatch.Elapsed.ToString("hh\\:mm\\:ss\\.ff");
}
// This method handles the button click. It changes the button text and starts
// or stops the stopwatch, depending on whether the stopwatch is running
private void btnStartStop_Click(object sender, EventArgs e)
{
if (stopwatch.IsRunning)
{
stopwatch.Stop();
Timer.Stop();
btnStartStop.Text = "Start";
}
else
{
Timer.Start();
stopwatch.Start();
btnStartStop.Text = "Stop";
}
}
}
Don't use DateTime for this. Instead, create a Stopwatch (in the System.Diagnostics namespace). You won't need to increment it yourself - just start it when the button is clicked, then evaluate its Elapsed property to get the duration elapsed (which is a TimeSpan type).
Yes, you'll also want a timer to periodically update the display. That timer can fire as often as you like, and can be imprecise - because it's not responsible for updating the stopwatch, just for writing the current value of the stopwatch to the display.
In summary:
DateTime is for representing a date and time of day.
DateTime.Now, DateTime.UtcNow, etc. give a mechanism to get the current date and time of day.
TimeSpan is for representing durations of elapsed time.
Stopwatch gives a mechanism for measuring elapsed time.
Separate the updating of the display from measurement of time. They are separate concerns.
Your project won't work because you never leave while.
You should try to use Timer.
Read about it here.
I think this video must help you.
How do I wait for a specified time while showing the remaining time to wait?
I now solved it like this but I feel like this is a really bad way to do it:
//This is running in a BackgroundWorker:
Stopwatch watch = new Stopwatch();
watch.Start();
while(watch.ElapsedMilliseconds != SecondsToWait * 1000)
{
TimeToNextRefresh = ((SecondsToWait * 1000) - watch.ElapsedMilliseconds) / 1000;
Thread.Sleep(1);
}
watch.Stop();
So here I am guessing that the condition (watch.ElapsedMilliseconds != SecondsToWait * 1000) is checked every millisecond.
So the main question is; In what period is the condition of while checked and/or how do I improve the code I've written?
It depends on what's the code inside while loop!
For example, if you write some really long/time-consuming code in a while loop, each iteration of the while loop, or course, will be longer than a while loop that only has short/fast code.
Compare these two while loops:
while (true) {
Console.WriteLine("Hello");
}
and
while (true) {
Console.Beep(5000);
}
Each iteration of the first while loop is faster than that of the second one because Console.Beep(5000) takes 5 seconds and Console.WriteLine only takes a fraction of a second.
So you can't rely on while loops to count time.
This is what you should do:
Create an instance of System.Windows.Forms.Timer, not the System.Timers.Timer nor the System.Threading.Timer. I find the first one the most useful (others are more advanced).
Timer timer = new Timer();
timer.Interval = 1000; // 1000 means 1000ms aka 1 second
timer.Tick += TimerTicked;
timer.Start();
Now the compiler will tell you that TimerTicked is not defined, so let's go define that:
private void TimerTicked(object sender, EventArgs e) {
}
Now you're all set. The code in TimerTicked will be called every one second.
Let's say you want to measure a time of 10 seconds. After 10 seconds, you want to do something. So first create a variable called secondsLeft in the class level:
int secondsLeft = 10;
Now in TimerTicked, you want to check whether secondsLeft is 0. If it is, do that something, else, minus one:
if (secondsLeft == 0) {
DoSomething();
} else {
secondsLeft--;
}
And secondsLeft is the time remaining! You can display it on a label or something.
To pause the timer, simply
timer.Stop();
The exact interval in which your while condition is checked is hard to predict. Thread.Sleep(1); only tells the operating system that you want your thread to sleep for at least 1 millisecond. There is no guarantee that your thread will be active again after exactly 1ms. Actually you can rather be sure that it will be more than that. The thread is scheduled again after 1ms, but there will be a delay until he gets his CPU time slot.
The interval you want for your loop actually depends how you want to display the remaining time. If you want to display only seconds, why would you update that display every millisecond, although the text would change only every 1000ms?
A loop like that is probably not a good way to implement something like that. I would recommend a System.Threading.Timer:
// this Timer will call TimerTick every 1000ms
Timer timer = new Timer(TimerTick, null, 0, 1000);
and implement the handler
public void TimerTick(object sender)
{
// update your display
}
Note that you will have the "update your display" part on the UI thread again, as this method is called by the Timer on a different thread.
This code is can really make an infinite loop if a calculation just take longer than 1 miliseconds.
You can achieve your desired behaviour with a simple System.Winforms.Forms.Timer like this snipped below :
private int tickCount = 0;
private int remaining = 10;
private void timer1_Tick(object sender, EventArgs e)
{
remaining--;
textBox1.Text = remaining.ToString();
}
private void Form1_Load(object sender, EventArgs e)
{
timer1.Interval = 1000;
timer1.Enabled = true;
}
With this you can countdown from 10 seconds and every tick you write to a textbox the remaining seconds
Hello people of stackoverflow.I am having an issue when i try to take a time-span and convert it to a string.
Here is the code:
private void timer1_Tick(object sender, EventArgs e)
{
timeLeft = timeLeft - 1;
TimeLabel.Text = TimeSpan.FromMilliseconds(timeLeft).ToString("h'h 'm'm 's's'");
}
Note that timeLeft is in milliseconds.
However whenever i try to pass this i get 2 sets of minutes sections.
Like this:
Although it should be this amount of time :
I see you´re updating the label every timer ticks and although it´s not shown in the code it looks like your timer interval its set to 1 second probably, Am I right?.
The first thing you´re doing bad is trusting the 1 second interval you set up previously in your timer and hard-coding your code to that interval. The fact is you can´t rely in the timer interval to be precise because most of the timers have a awful resolution time of approximately 14 - 16 ms therefore that´s not a precise way to measure time.
You should use instead the time System.Diagnostics.Stopwatch class which uses the Win32 APIs QueryPerformanceFrequency and QueryPerformanceCounter. Those are the more reliable ways and fast ways to measure time due to the fact that Windows isn´t a Real Time Operation System.
As for how the code will look using I let a sample which should be pretty easy to adapt for you. Besides I include a solution for your TimeSpan - String translation trouble.
class Program
{
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
Console.WriteLine("Starting..");
sw.Start();
Console.ReadLine();
sw.Stop();
Console.WriteLine("Elapsed time {0}:{1}:{2}:{3}", sw.Elapsed.Hours.ToString("00"), sw.Elapsed.Minutes.ToString("00"), sw.Elapsed.Seconds.ToString("00"), sw.Elapsed.Milliseconds);
}
}
Be careful while using the System.Diagnostics.Stopwatch properties, there is a big difference in using the Elapsed.Ticks property and the ElapsedTicks property which it´s explained here.
Hope it helps!!
Due to the fact that there won't be any guarantee that the timer will be fired exactly every millisecond, you have to save a start time and then calculate the elapsed time by subtracting the start time from the current time.
Here is a code snippet to illustrate it:
private DateTime _StartTime;
private void OnCheckBoxTimerEnabledCheckedChanged(object sender, EventArgs e)
{
_StartTime = DateTime.UtcNow;
timer.Enabled = checkBoxTimerEnabled.Checked;
}
private void OnTimerTick(object sender, System.EventArgs e)
{
var now = DateTime.UtcNow;
labelTimeElapsed.Text = (now - _StartTime).ToString("h'h 'm'm 's's'");
}
In that case you also don't need to fire the timer every millisecond. Just fire it every 100ms to be accurate enough for the users eye.
And another tip:
If you need to calculate relative times on your own you should always stick to DateTime.UtcNow and NOT DateTime.Now. So you won't get into trouble when your timer is running when you switch from normal time to summer time or vice versa.
there is nothing wrong with your code. but i guess you Think there is since the above sample shows
2:02:56 and the other 02:03:00 wich is rather Close missing some 3200 milliseconds...
what is the actual value of timeLeft?
Read some more in the documentation on customizing timespan strings
Using a Timer's Tick event to track passing time will result in inaccuracies as Lasse V. Karlsen mentioned in their comment on your question.
What you want to do is store a timestamp (DateTime.Now) when the timer begins, and compare that with a new DateTime.Now each time the timer ticks, like so:
DateTime timestamp;
TimeSpan timeLeft;
private void begin_timer()
{
timestamp = DateTime.Now;
timer1.start();
}
private void timer1_Tick(object sender, EventArgs e)
{
timeLeft = DateTime.Now - timestamp;
TimeLabel.Text = timeLeft.ToString("HH:mm:ss.fff");
}
This is my second question on StackOverflow here. I posted my first question a while ago and got a working reply in no time, much impressed, much appreciated.
Anyways, so what I want to know is, how to get a DispatcherTimer to work and show time in a certain textbox and stop it when it reaches a certain time (let's say 60 seconds) and perform a function after 60 seconds.
What I'm basically using this for is :
Making a game, which has to stop after 60 seconds and show the scores or related stuff. So this requires me to show the time in a textbox and perform a function at 60 seconds or after that.
Here's more information :
Textbox is called "timerbox"
Here's the code I've tried :
DispatcherTimer dt = new DispatcherTimer();
private void TimerStart(object sender, RoutedEventArgs e)
{
dt.Interval = TimeSpan.FromSeconds(1);
dt.Tick += dt_Tick;
dt.Start();
}
int count = 0;
void dt_Tick(object sender, object e)
{
count = count + 1;
timerbox.Text = Convert.ToString(count);
}
It doesn't show the time in textbox, plus I don't know how to make it stop at certain point and perform a function.
Thank you for reaching here, please leave answers with full explanation as I'm a complete beginner :)
P.S. I'm using Windows Store App Development Environment in Visual Studio 2013.
And there's no "Timer" in it as there is in normal C# Environment.
AOA.
I am recently started learning c#. (interested in windows form application). Hope this help you.
if you just want to set timer for a curtain event.....
recommend you using timer ( in toolbox )......
follow steps, when you double click on timer1 VS will create a timer1_Tick function for you which will be called every timer you timer ticks.....
now what you want to do when timer1 icks write it in there....like this....
private void timer1_Tick(object sender, EventArgs e)
{
//enter your code here
}
now write timer1. and VS will display a list of avaliable function....
for example,
timer1.Interval = (60*1000); //enter time in milliseconds
now when you want to start the write......
timer1.Start();
and to stop timer at any timer call
timer1.Stop();
if you want to repeat timer just write timer1.start() in that tick function.....
plus, to set textbox text equal to timer1 time use something like
textBox1.Text = Convert.ToString(timer1.Interval);
Click here for more information on timer class
hope this help you,
in case of any confusion, just comment,.....
The normal flow of a DispatcherTimer would look like this:
First Set up your new Object, set up the a new EventHandler that will run your desired code each Tick and Set the Timespan for the desired Tick Interval.
public MainPage()
{
this.InitializeComponent();
timer = new DispatcherTimer();
timer.Tick += new EventHandler<object>(timer_Tick);
timer.Interval = TimeSpan.FromMilliseconds(bpm);
}
Set The Timer_Tick Envent
async Void timer_Tick(object Sender, object e)
{
await this.Dispatcher.RunAsync(Windows.UI.core.CoreDispatcherPriority.High, () =>
{
//Run the Code
textBox1.text = timer.interval.TotalMilliseconds.ToString();
});
You have to have a trigger to Start the Dispatcher(and to stop if you need to), for example a button
private void StartButton_Click()
{
timer.Start();
}
This example was done using The new windows 10 Universal App platform within VS2015, but I think it should look about the same in a normal windows 8 App
I am trying to get a timer run every minute in sync with the system clock (00:01:00, 00:02:00, 00:03:00, etc). This is my code.
private System.Timers.Timer timer;
public frmMain()
{
timer = new System.Timers.Timer();
timer.AutoReset = false;
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Interval = GetInterval();
timer.Start();
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
System.Diagnostics.Trace.WriteLine(DateTime.Now.ToString("hh:mm:ss tt"));
timer.Interval = GetInterval();
timer.Start();
}
private double GetInterval()
{
DateTime now = DateTime.Now;
return ((60 - now.Second) * 1000 - now.Millisecond);
}
It runs perfectly on my home PC.
12:12:00 AM
12:13:00 AM
12:14:00 AM
12:15:00 AM
12:16:00 AM
12:17:00 AM
12:18:00 AM
12:19:00 AM
12:20:00 AM
12:21:00 AM
However I'm getting weird results on my VPS (windows server 2003).
12:11:59 AM
12:12:59 AM
12:13:00 AM
12:13:59 AM
12:14:00 AM
12:14:59 AM
12:15:00 AM
12:15:59 AM
12:16:00 AM
12:16:59 AM
12:17:00 AM
12:17:59 AM
12:18:00 AM
12:18:59 AM
12:19:00 AM
12:19:59 AM
12:20:00 AM
12:20:59 AM
12:21:00 AM
Is it because System.Timers.Timer does not work well on windows server 2003? Or is it an issue with my VPS?
Instead of using DateTime.Now and pulling the individual parts, just use the Ticks. Get the ticks when you start, then calculate what the ticks should be for the next timer tick. Once that timer tick occurs use the last value to calculate what the next value should be.
Example:
private const long MILLISECOND_IN_MINUTE = 60 * 1000;
private const long TICKS_IN_MILLISECOND = 10000;
private const long TICKS_IN_MINUTE = MILLISECOND_IN_MINUTE * TICKS_IN_MILLISECOND;
private System.Timers.Timer timer;
private long nextIntervalTick;
public void frmMain()
{
timer = new System.Timers.Timer();
timer.AutoReset = false;
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Interval = GetInitialInterval();
timer.Start();
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
System.Diagnostics.Trace.WriteLine(DateTime.Now.ToString("hh:mm:ss tt"));
timer.Interval = GetInterval();
timer.Start();
}
private double GetInitialInterval()
{
DateTime now = DateTime.Now;
double timeToNextMin = ((60 - now.Second) * 1000 - now.Millisecond) + 15;
nextIntervalTick = now.Ticks + ((long)timeToNextMin * TICKS_IN_MILLISECOND);
return timeToNextMin;
}
private double GetInterval()
{
nextIntervalTick += TICKS_IN_MINUTE;
return TicksToMs(nextIntervalTick - DateTime.Now.Ticks);
}
private double TicksToMs(long ticks)
{
return (double)(ticks / TICKS_IN_MILLISECOND);
}
You could probably do this using Seconds and Milliseconds like you were. The trick is to have one starting point to calculate off of (rather then determining how many seconds to the next minute). If there are additional concerns not mentioned in the original problem, like the code in timer_Elapsed might take longer then a minute to run, then you will need to add code to handle this.
Please leave a comment if you need additional help. Otherwise please select a correct answer.
((60 - now.Second) * 1000 - now.Millisecond)
This means that if now.Second happens to be 59 your time will fire again in less than a second. This is the reason for your weird results (the timer not firing at exactly 0 second offsets).
It's probably more productive for you to have the timer fire every second, keep the previous date/time value in a separate variable, and update the on-screen timer when the second portion changes.
Normal timers like System.Timers.Timer are not accurate and not nearly good enough to achieve a 1 msec interval.
Firstly they have an internal update rate of 10-15 msec. Secondly depending on the system other threads may run for ~15 msec delaying your timer before Windows forces them to yield.
If you want more accuracy than Timer use System.Diagnostics.Stopwatch as reported in another thread it can go from 0.3 ms and is integrated with your .NET environment.
Another option is to use a multimedia time (accurate to around 1ms).
Either way here is an excellent tutorial on the issue.
Breaking it down:
Timer drift normally adds a delay to the timer. But you are seeing the opposite happen. As timers do not have millisecond accuracy (they are only accurate to in the 15ms range) they will often be fired with that granularity. So in effect firing the timer a few milliseconds before the minute mark on some occasions (causing it to fire immediately afterwards aswell). If you require it to only fire in the new minute I would add in a few milliseconds of a wait time to compensate (5ms should do it).
Your home pc is not so fast (which means it exhibits extra timer drift dealing with the timer handler) and normally fires the event in the next second. Your work PC sometimes manages to handle the timer event quick enough that it records 59 seconds past (which I do believe is truncated and probably 59.900 ~ 59.999). This may also occur if the machine is multi-cored as there is no thread yeilding delay and the timer can be fired very quickly.
That is the cause of your Timer irregularities.
Hi another example is use the Timer from System.Windows.Threading.
using System;
using System.Windows.Threading;
namespace Yournamespace
{
public partial class TestTimer
{
DispatcherTimer dispatcherTimer1m;
public TestTimer()
{
dispatcherTimer1m = new DispatcherTimer();
dispatcherTimer1m.Tick += new EventHandler(DispatcherTimer1m_Tick);
dispatcherTimer1m.Interval = TaskHelper.GetSyncIntervalms;
dispatcherTimerm.Start();
}
private void DispatcherTimer1m_Tick(object sender, EventArgs e)
{
try
{
dispatcherTimer1m.Stop();
//Do your effort here
}
catch (Exception exc)
{
//Your exception handled here
}
finally
{
dispatcherTimer1m.Interval = TaskHelper.GetSyncInterval1m;
dispatcherTimer1m.Start();
}
}
}
public class TaskHelper
{
private const ushort internalUpdate = 15;//ms
public static TimeSpan GetSyncInterval1m => new TimeSpan(0, 0, 0, 60,internalUpdate).Subtract( new TimeSpan(0, 0, 0, DateTime.Now.Second, 0));
}
}
Remember that Windows Server is by default set up to share resources with background tasks more willingly than the client versions so timer accuracy can be affected if the server is running a number of background tasks.
You could try temporarily changing it to prioritise the foreground task to see if that gives different results - the setting is somewhere in the System control panel, you're looking for two radio buttons, one that says "Programs" and one that says "Background services" or similar.