Is there a way to run the Timer so that it starts at exact full second?
stateTimer = new Timer(someCallback, null, 0, 1000);
This one will start right away, repeating each second, but the problem is it will start exactly when I run the program which may result in 13:14:15.230 start.
I would like 13:14:15.000 start. Something like:
stateTimer = new Timer(someCallback, null, DateTime.Now.Date, 1000);
Is that possible?
EDIT:
After doing the console log:
Console.WriteLine($"Time: {DateTime.Now.ToString("HH:mm:ss.fff")}");
I've noticed that 1 second interval actually gets incremented by more than one second (about 1,02 each iteration) so after 50 iterations one second is skipped. I have solved my problem by making timer run each 800ms instead. Not ideal solution, but it works, and second never gets skipped (and I have no problem in triggering the same second twice).
stateTimer = new Timer(someCallback, null, 0, 800);
No that is not possible. That would require you to exactly know when the CPU thinks it is a good idea to start to execute your timer code. Even if you would Thread.Sleep for the remaining time, it would still not mean the code is executed at the very millisecond you want to.
Instead, if you just want to do this for formatting, you can use a custom date/time format to do that.
I had to do something similar in a program that displayed the time and displayed the number of minutes and seconds until the user could do something.
The original code used a 1000 ms timer. This had the problems described by the original poster. I created a thread. The thread had a loop:
private ManualResetEvent myThreadRequestExit = new ManualResetEvent(false);
while (!myThreadRequestExit.WaitOne(1000 - DateTime.UtcNow.Millisecond))
{
// Do the one-second work here
}
The loop will exit and the thread will terminate when MyThreadRequestExit is set.
Although it may fire a few milliseconds after the start of the second it is close enough that the user perceives the timer as ticking when it should and it does not lose seconds as long as the work can be done in less than a second.
Just add this line before you start your timer. Sweet and simple :)
Thread.Sleep(1000 - DateTime.Now.Millisecond);
Related
I must be missing something obvious, but I simply do not understand why my main form in my Windows Forms Application is taking 20 seconds to show up. My program is an attempt to take a TPL code example I found in a console application example and make in work in a windows form/gui. I KNOW the queuing of tasks will take 20 seconds to complete, but does that section of code occur so fast that the form has not had time to finish initialization? I tried putting a delay right after "InitializeComponent();" in hopes that it would give the form time to come up; and also tried to put just a messagebox after, but still get the same delay after my inserted delay. There is no form_load method, so there is nothing to check there.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// Time the test(s)
Stopwatch stoppwatch = new Stopwatch();
stoppwatch.Start();
Console.SetOut(new ControlWriter(tb1)); // just redirects console.writeline to the form's textbox "tb1"
// #################################### job queue ########################################
var q = new TPLDataflowMultipleHandlers(); //
var numbers = Enumerable.Range(1, 10);
foreach (var num in numbers)
{
F1TimeDelay(2);
q.Enqueue(num.ToString());
}
// Stop the timer and return the elapsed number of milliseconds.
stoppwatch.Stop();
Console.WriteLine("XXXXXXXXXX <STATUS> Elapsed time = {0} minutes. XXXXXXXXXX", (int)stoppwatch.Elapsed.TotalMinutes);
}
As an aside, when the form does finally show up, the text box is full of the messages I was expecting to see from the launched threads (info like thread id, etc).
F1TimeDelay(2) is a 2 second delay, while the queued jobs are just 10 second long tasks to demonstrate the 10 tasks running in parallel. The numbers sent to the queue end up being job numbers for the 10 tasks.
Because somewhere between the Constructor and FormShown Event, you are calling code that takes 20+ seconds to complete.
While I can see nothing in the constructor, that is litearlly just the start of the loading process: https://learn.microsoft.com/en-us/dotnet/framework/winforms/order-of-events-in-windows-forms
Generally the earliest moment you should retreive any data or do anything else, is in the Shown Event. And even then, a long running operation such as this should be done with some form of Multitasking/Asynchronous operation. You have to figure out what it is, but my guess is for a Disk or Network/Database Access.
If you want to do measurements with a hope of correctnes, you need to start the StopWatch in the Constructor, and only stop/show the result in Shown. And even then your Shown Event might be the 1st one called with the hard/long work comming later, so it might miss whatever causes the issues. Your Stopwatch also does not include the Designer created Elements. The Designer code is executed with InitializeComponents(). Of course with delay on such an order of Magnitude, it should be feasible to just output DateTime.Now regulary.
The form will show sometime after the constructor is done. If you put the long running task queuing code into the constructor, the form wont show until this long running code is done.
Instead add a button to the form and create a click handler for it. put the long running code there. Then the form will show up and you can click the button. But then the form will freeze, because of the task queuing, i guess.
so I've just made a simple snake game in WinForms and I've only got one problem left. The idea is that I'm gonna implement a power-up that speeds up the player for 10 seconds. I've tried using thread. sleep method to create a timer but that sleeps the entire program. I've also tried playing with the task.delay method but without success.
Am I going about this problem the wrong way or am I just missing something? Do you have any tips to get me on the right path? I'm quite new to this so this might be an easy fix.
var watch = new Stopwatch();
watch.Start();
using (var task = Task.Delay(10000))
{
speedUp = true;
task.Wait();
}
watch.Stop();
speedUp = false;
This is my attempt at the delay. But it seems to pause the entire program for 10 seconds before it continues.
Thanks
You may want to check the past time by looking at a clock within your game loop. The property Environment.TickCount provides you with the milliseconds since the last boot or you could do it with DateTime or Timespan. Now instead of sleeping you could check if 10'000 milliseconds have past since the activation of the power-up. This way nothing will get blocked and collecting multiple power-ups within 10 seconds won't screw up the deactivation process.
I write a c# program to count down 5 seconds. What I do is:
new Task(() =>
{
try
{
this.Invoke((Action)delegate()
{
label1.Text = "5"; // 4, 3, 2..etc
});
}
Thread.Sleep(1000);
}
catch
{
// form could be disposed
break;
}
}
}).Start();
This works on my PC, however, when I copied the program to a window tablet, the Thread.Sleep(1000) gives more than 1 second. In other words, it takes more than 5 seconds (in fact more than 10 seconds) to update the label from 5,4,3,2,1. Alternatively, it takes too long to update label1.Text = "5", etc? It does not make sense to me. I wonder what is wrong?
Sleep will wait at least that long before activating the thread again, but it can always be longer than that. After the one second time has passed the thread becomes eligible to execute by the CPU scheduler, and the scheduler is able to run it whenever it wants to. If it's particularly busy, and/or is using a scheduling algorithm that doesn't focus on quickly allowing newly active threads to run, it could be some time.
Servy's answer is correct. For more details, please read the documentation:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686298.aspx
which states:
Note that a ready thread is not guaranteed to run immediately. Consequently, the thread may not run until some time after the sleep interval elapses. For more information, see Scheduling Priorities.
The priority documentation is here:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms685100.aspx
More generally though: you are doing something deeply wrong. Do not ever use Sleep like this. If you want to wait some amount of time then use a timer or use a Delay task. Never sleep a thread like this outside of test code. The right way to write your code is probably something like
for (int countdown = 5; countdown > 0; countdown -= 1)
{
label1.Text = countdown.ToString();
await Task.Delay(1000);
}
Or, make a class that has a timer and a counter, start the timer to tick a few times a second, compare the current time to the time when you last updated the label, and if more than a second has elapsed, update the label.
What I want to accomplish it the following thing:
I have a lot of "checks(if/else if etc)" inside a timer, that his interval is 1000 ms,
there is a text file that getting updated and the timer read it every 1000 ms and check for some specific changes,
under 1 of those conditions if it is true the timer, i need to wait 10 sec and then read another text file and then continue with the rest of the timer code.
but in the mean time the timer keep running under those 10 sec and preform the checks every 1sec for all the other conditions and this 1 also.
what i thought to do it
if the conditions i wanted it true i will start a new timer with 10sec interval and it will continue with the code of that specific part.
but what i have hard time to accomplish is how to pass parameters into that timer
such as
newTimer.Start(int "parameter", string "parameter b", list<string> parameters c")
etc etc
or if you got any other idea i will be glad to hear.
To pass parameters, you can always use Tuple.
newTimer.Start(Tuple.Create(param1, param2, param3));
You might not need to have two timer if you do the logic correctly.
Timer *run every second*
Check file
If file has flag Then save in variable the current date + 10 seconds
If current date > saved date Then Check the other file
You need to consider that a System.Windows.Forms.Timer will run on the GUI thread (the thread that run the containing form's message loop / pump), as it uses window messages (WM_TIMER) that are processed by the GUI thread. Because of that, any code that runs under any System.Windows.Forms.Timer in your form will execute synchronously. So, if your start a new System.Windows.Forms.Timer which blocks for 10 seconds, all your other timers will be blocked as well (since the message loop is blocked).
Consider using a System.Threading.Timer or System.Timers.Timer, as they run the timer callback on a different thread. This way, your code will run pretty much as you'd want - every one second the method will be running, regardless of weather the previous call completed or is still blocking (waiting 10 seconds).
I have a timer. But it starts a second late.I mean, i am clocking a time according to the timer. But the time in the clock, which updates through timer, is one second less then the actual time elapsed. The timer starts off a second late. How to set my timer to start at right time to show actual time? this is the code inside tick event:
if (currentState == play)
{
m_StatusLabel.Text = String.Format("Playing {0} ", format(timeCounter));
timeCounter++;
}
Here timeCounter is updating with each second.
Standard System.Windows.Forms timers give no guarantees about 'metronome quality'. For that, you would need either a Systems.Threading.Timer or a System.Timer.
Ref: Comparing the Timer Classes in the .NET Framework Class Library
There are no timers available that will gaurantee true-time accuracy, not even System.Threading.Timer can do that. For example, when you ask Threading.Timer to fire in 30ms, it might actually take 40ms or 200ms. Or if you ask for 1 second, it might fire in 1.01 seconds. In won't take long before your time is inaccurate.
The reason for this is that the timer makes the callback thread schedulable, but it still takes time for the thread scheduler to actually call the thread. Various operations the system is performing can delay that callback.
A Windows timer makes only one guarantee: it won't fire before the timeout interval elapses. Specifically, a thread will never receive a timer event while there are messages in its message queue.
Consequently you can't use timers to implement a clock. If you want to update a status message to show how long something has been playing, then you could try this: record the start time, and when your timer ticks get the current time, subtract the start time, and dislay the difference. Your status message won't be updated exactly every second, but when it is updated it will be correct.
Show a number 1 greater:
if (currentState == play)
m_StatusLabel.Text = String.Format("Playing {0} ",
format(++timeCounter) );
NOTE
Please consider the reason of those who suggested displaying the elapsed time as current time - start time. That is the way this is usually done. It is more accurate; a timer can be irregular on a busy system. It is still possible to update the displayed value every second. Pseudo code here for now(). This requires acquiring current time and performing a time difference.
if (currentState == play)
m_StatusLabel.Text = String.Format("Playing {0} ",
format( (now() - start)/1000 );
See Also:
1. DateTime.Subtraction
2. DateTime.Now