Why is basic time/date output taking two seconds to display? - vb.net

What I have:
I'm displaying the current time and date (real-time) at the bottom of a form using a timer element.
I'm using two labels to display the time and date respectively.
What I need:
I need the time and date labels to display as instantly as everything else.
My problem:
There is a two second delay in the displaying of the time and date labels.
My code:
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
'Format time and date labels.
TimeMain.Text = Format(Now, "hh:mm:ss")
DateMain.Text = Format(Now, "dddd, d/MM/yyyy")
End Sub
Note: The above is preceded by a Form_Load sub that simply defines a default accept button. The above is followed by 5 by five short subs.
Edit:
Though the steps for reproducing the problem have already provided in the comments I've been requested to reiterate here. The only difference between the two code blocks posted in this question is that I've left the label text at default to spare the reproducer having to type anything.
Drag two labels and a timer onto a new form and use the following code:
Public Class Form1
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
'Format time and date labels.
Label1.Text = Format(Now, "hh:mm:ss")
Label2.Text = Format(Now, "dddd, d/MM/yyyy")
End Sub
End Class
For the timer's properties, Enabled is defined as True and Interval as 1000.

I know this isn't exactly an answer but this is too long to fit in a comment. Also read here for a little more information on timers:
Why are .NET timers limited to 15 ms resolution?
Does the System.Windows.Forms.Timer run on a different thread than the UI?
Timer elapsed events from what i understand (which could very well be wrong) aren't guaranteed to fire exactly when the time has elapsed, it's more of... put it in queue to fire once the timer has elapsed.
Imagine your application/timer started at "00:00:01.999" and your label states "00:00:01" as the current time.
Exactly 1000 MS later you're at "00:00:02.999 and the elapsed event fires, completing at "2014-01-01 00:00:03.0045" and your label is updated to "2014-01-01 00:00:03" - you've already "lost" a second here.
You could try setting your interval to something lower than one second (say 750) which would get you a potentially more accurate looking counter. Additionally, ensure you're setting the timer labels on form load. I've not worked very much with timers and i'm having trouble finding the article i was reading earlier but you might need to worry about UI locking depending on the timer type used (there are apparently 4 timer classes in the .net framework.) Perhaps someone else can expand on that though, I don't know much about winforms.

Related

Visual Basic: Image moves up and and then back down after a button click

I am attempting to make a character appear to jump straight up in the air and then come back down and return to the same level he started at. (y=100) The code below seems to make the program fight itself and move him up and down at the same time.
I have tried countless methods and all of them resulted in the guy either going up and not coming back down or flying off the page.
Private Sub btnJump_Click(sender As Object, e As EventArgs) Handles btnJump.Click
tmrJump.Start()
End Sub
Private Sub tmrJump_Tick(sender As Object, e As EventArgs) Handles tmrJump.Tick
For intCounterUp As Integer = 100 To 15
picSpaceRunner.Location = New Point(intCounterX, intCounterY)
intCounterY = intCounterUp
Next intCounterUp
For intCounterDown As Integer = 15 To 100
picSpaceRunner.Location = New Point(intCounterX, intCounterY)
intCounterY = intCounterDown
Next intCounterDown
End Sub
End Class
The code is running with no delay, so you're at the mercy of the machine.
I'm not a professional game coder, so I couldn't explain the intricacies of modern game engines. However, one of the basic ideas I learned a long time ago is to control your game/animation loop. Consider the frames per second.
In your code, it could be as simple as adding a delay within each loop iteration. If you want the character to complete his jump in 2 seconds (1 second up, 1 second down), then divide 1000 (1 sec = 1000 ms) by the number of iterations in each loop and delay by that amount. For example, you have 85 iterations, so each iteration would take approximately 12 ms.
If you don't mind blocking a thread, you can do this very easily with Threading.Thread.Sleep(12). If blocking is an issue, you'll likely want to use an external timer.
I found this link during a Google search. He explains how to set up a managed game loop in VB.Net.
http://www.vbforums.com/showthread.php?737805-Vb-Net-Managed-Game-Loop
UPDATE: Per OP's comment...
To do this using timers, you'll want to manipulate the character object directly within the Timer event handler (Tick). You wouldn't use loops at all.
Set the Timer's Interval to the value discussed earlier - the number of ms corresponding to how long it takes to move 1 pixel. Then, in the Timer's Tick handler, set the character object's Location equal to a new Point with the new value. Also in the Tick handler, check your upper bound (15), then reverse the process until it hits the lower bound (100).
For example,
Private Sub tmrJump_Tick(sender As Object, e As EventArgs) Handles tmrJump.Tick
If (intCounterY > 15 And blnGoingUp == True) Then
picSpaceRunner.Location = new Point(intCounterX, intCounterY - 1);
End If
... Remaining Code Goes Here ...
End Sub
Do not put the loop in the timer_tick. Increase or decrease the height by set interval instead and then check if the image had reached the maximum or minimum height.

How can I get a program to run automatically at specific times a day (VB.NET)

The application I'm developing right now allows the user to update an Excel sheet or Sql database for set metrics twice a day. The program does this by popping up at certain times (e.g. 6:00 AM, 5:00 PM, 3:42 PM, whatever the user sets). By having the program pop up at certain times, the program ("Auto Excel It!!!") allows you as the user to track set data (say, sales calls, sales presentations, meetings, number of hours coding, number of jalepeƱo burritos eaten, etc.).
How can a developer get this program to "pop up"/start/function automatically at specific times through the means of the Windows Scheduler API (or something better)?
Here's how my understanding's evolved lately:
Nothing --> Use Timers As The Program Runs In The Background --> Use Windows Scheduler's API To Run Automatically (Current) --> Possible New Understanding From Your Answer
For example, I'm aware of: DispatcherTimers, Timers, another timer I'm not aware of, Sleep(), Windows Scheduler. But with these in mind, I don't know what to do regarding the following: Automatically starting a program via Windows Scheduler; Preserving computer resources if a timer is used; or even how to get this top pop up automatically.
Update 1:
#nfell2009:Your logic helped me out big time. At first I had to toy around with converting your Timer here to a DispatcherTimer (WPF forms standard, it seems). Then, I switched the the "Handles" for the Sub tCheckTime to "AddHandler tCheckTime.Tick, AddressOf tCheckTime_Tick" --- Why I had to do this is a good question.
Then, once I had the basic EventHandlers set up, your idea for comparing the user's text (As Date) to the System.Date is good--When I screwed something up and couldn't get the code to work, I switched it up and converted System.Date to a String--i.e. I went from String->Date To Date->String... That's when I got the Timer to work. When my System.Time ticked to 3:12 PM, the MsgBox popped up with "Your Message Here."
(A Quick (Evil) Thank You! I've spent four-plus hours getting this to work)
Code:
From Using "Handles" At tCheckTime_Tick (Which seems like it 'should' work)
Private Sub tCheckTime_Tick(sender As Object, e As EventArgs) Handles tCheckTime.Tick
...
End Sub
To AddHandler blah, AddressOf tCheckTime_Tick (Does work)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Loaded
'MsgBox(Now().ToString("hh:mm")) 'String.Format("{hh:mm}", Now()))
AddHandler tCheckTime.Tick, AddressOf tCheckTime_Tick 'Why is this necessary?
tCheckTime.Interval = New TimeSpan(0, 1, 0)
End Sub
Public Class Form1
Dim iSetTime As Date
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub btnSetTime_Click(sender As Object, e As EventArgs) Handles btnSetTime.Click
If (tCheckTime.Enabled = True) Then
tCheckTime.Enabled = False
End If
iSetTime = txtTHour.Text + ":" + txtTMinute.Text + ":" + txtTSecond.Text
tCheckTime.Enabled = True
End Sub
Private Sub tCheckTime_Tick(sender As Object, e As EventArgs) Handles tCheckTime.Tick
If (TimeOfDay = iSetTime) Then
MsgBox("Your Message")
End If
End Sub
End Class
You will need error checking for the textboxs, but its simply:
3 textboxs with indication of which is which, so maybe a label each with H, M, S - or something.
A button which will set time and a timer. Naming:
Textboxs
Hours = txtTHour
Minutes = txtTMinute
Seconds = txtTSecond
Buttons
Start Button = btnSetTime
Timers
Timer = tCheckTime
I can think of two easy ways:
Have your program calculate the time until it should next appear in seconds and then set a timer with an elapsed time such that when the tick event is raised you can do whatever you need to do.
Use MS Task Manager to launch your program when and as needed.

VB.NET realtime clock in a textbox

How can I make it so that when I load the form a textbox will show me (dd/mm/yyy hh:mm:ss) format clock that is actually moving and is synced with the system?
I tried googling it but so far couldn't find anything that works. Most answers dealt with making labels into clocks but I figured it's the same with textboxes and tried doing what they said with no results. It shows me the time but it's just the time when the form loaded not an actual moving clock. I think most of the answers I found on google are dealing with older versions of VB that's why I can't get it to work.
P.S. I'm just learning coding so the simpler the code the better. Many step by step (like I'm 5) comments are appreciated as well. Thank You
Add a Timer to your form, and add this code to it's tick event.
Textbox1.text = Format(Now, "yyyy-MM-dd hh:mm:ss")
You now have a textbox which tells you the current date and time.
Don't forget to enable your timer, though!
Try to put your time and date string inside a timer. this is how it looks like:
Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
TimerText.Text = TimeString
DaterText.Text = DateString
End Sub
It will surely show you a moving/real time clock that was sync to your computer. :)

What would be a better way to make a calendar than using labels?

I've created my own winforms month-view calendar in VB.net.
To do it I've used a table layout panel, with 42 separate cells. In each of the cells is a label called lblDay1, lblDay2, etc.
When I load the page, the labels are all written to with the correct numbers for that month.
Dim daysInMonthCnt As Integer =31 'Assume 31 days for now
Dim firstDay As Integer = Weekday("1/" & Now.month & "/" & Now.year) 'Get weekday for 1st of month
For dayCount As Integer = firstDay To daysInMonthCnt
Dim lbl As Label
lbl = CType(pnlMonthBody.Controls("lblDay" & dayCount), Label)
lbl.Text = dayCount 'Write to label
Next dayCount
Unfortunately, that turns out to be incredibly slow to load. Can anyone please suggest a faster method.
Just writing values to a so small number of labels is a really fast process. The problems you are experiencing have to do most likely with the VB.NET "problems" while refreshing the contents of GUI controls; the best way to fix this is looking into multithreading, as suggested by FraserOfSmeg.
As far as I think that this is a pretty simplistic GUI with a low number of controls and a not too demanding algorithm (big amount of/long loops is the prime cause of GUI-refreshing problems), you might get an acceptable performance even without relying on multithreading. In your situation, I would do the following:
A container (the TableLayoutPanel you are using or something
simpler, like a Panel) including all the labels at the start. In
case of not getting too messy (what does not seem to be the case,
with just 42 labels) I would include them in the "design view"
(rather than at run time).
A function populating all the labels depending upon the given month.
A "transition effect" for
the container called every time the user selects a different month.
You can accomplish this quite easily with a Timer relocating the
container (e.g., when the button is clicked the container's position
is set outside the form and then comes back gradually (20 points per
10ms -> made-up numbers) until being back to its original position).
Synchronising the two points above: the values of the labels
will start changing when the transition starts; in this way the user
will not notice anything (just a nice-appealing transition
month to month).
This GUI should deliver the kind of performance you are after. If not, you should improve its performance by relying on additional means (e.g., the proposed multi-threading).
SAMPLE CODE TO ILLUSTRATE POINT 3
Add a panel (Panel1), a button (Button1) and a timer (Timer1) to a new form and the code below.
Public Class Form1
Dim curX, origX, timerInterval, XIncrease As Integer
Dim moving As Boolean
Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
If (curX >= origX) Then
If (moving) Then
curX = Panel1.Location.X
moving = False
Timer1.Stop()
Else
curX = 0 'getting it out of the screen
moving = True
End If
Else
curX = curX + XIncrease
End If
Panel1.Location = New Point(curX, Panel1.Location.Y)
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Timer1.Start()
End Sub
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
XIncrease = 100
timerInterval = 100
Panel1.BackColor = Color.Maroon
origX = Panel1.Location.X
curX = origX
With Timer1
.Enabled = False
.Interval = timerInterval
End With
End Sub
End Class
This is very simplistic, but shows the idea clearly: when you click the button the panel moves in X; by affecting the timerInterval and XIncrease values you can get a nice-looking transition (there are lots of options, bear in mind that if you set curX to minus the width of the panel, rather than to zero, it goes completely outside the form).
If you're purely interested in speeding up your code I'd suggest running the loading code on multiple threads simultaneously. This may be overkill depending on your application needs but it's a good way to code. As a side note so the program looks a little more slick for the end user I'd suggest always running time consuming processes such as this on a separate thread(s).
For info on multithreading have a look at this page:Mutlithreading tutorial

Loop to check time in VB.NET

So I'm kind of new to VB and am just playing around with a little project, I currently need a loop that is constantly checking the systems clock to see if it's equal to a certain time.
While Not myTime.Hour = 24
If TimeOfDay = newTime Then
nfi.ShowBalloonTip(15)
intRandNumb = RandomNumber(1, 15)
dblAddMinutes = intTime + intRandNumb
newTime = TimeOfDay.AddMinutes(dblAddMinutes)
End If
End While
I have this right now, but obviously it's grinding everything to a halt and using 50% of my cpu in the process, I just would like to know what I can substitute in or change to make this loop run better and perform how I need it to.
you can add
Threading.Thread.Sleep(0),
this will cause a context switch and greatly reduce the CPU usage
Also consider using a timer object to be called every 10 or 100 ms, this will also be better in usage then having a loop
You can use
Threading.Thread.Sleep(0)
This will cause the working thread to yield the rest of it's current timeslice which will reduce the cpu usage quite a bit. However you should consider whether you really nead busy waiting for the time or if you could get away with setting a timer to count down the difference between the current time and the expected time, e.g.:
var t = new System.Timers.Timer((DateTime.Now - DateTime.Now).TotalMilliseconds);
t.Elapsed = DoSomething;
t.Start();
checking the systems clock to see if it's equal to a certain time.
There are two "correct" ways to do this:
Build a normal app that doesn't care what time it is, and set it up in windows as a schedule task.
Check the time once and calculate how long until the desired time. Then set up a timer to wait for that exact duration.
Under no circumstance should you keep polling the system clock for something like this that will just run once.
As Joel pointed out, you should try using a timer instead. I'm not sure if your app is a form or console or other, so I'll try to be generic and use System.Timers.Timer.
The code here (interval is set at 10ms, change to a value of your need):
Private timer1 As System.Timers.Timer
Const interval As Integer = 10
Sub initTimer()
timer1 = New System.Timers.Timer(10)
AddHandler timer1.Elapsed, AddressOf Me.timer_Elapsed
timer1.Start()
End Sub
Sub timer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)
'do your stuff here
'Console.WriteLine(e.SignalTime.ToString())
End Sub