My question deals with Timer activated clocks. Upon research the most similar situation is found here:
Two timers with two different intervals C# Form
Situation: I have an application being used for a game. In this game, there are many instances where a user must be able to create clocks and timers that need to be accurate within a second and if clocks, follow UTC Time.
Due to the need for variables to be used across forms, they are declared in a module.
Module Global_Variables
' String Variables
' frmMain
Public strMDbPath As String
' Date & Time Variables
'frmMain
Public dtLocalTime As DateTime
Public dtEveTime As DateTime
End Module
"frmMain" the main form, uses two clocks. Clock 1 is local time and clock 2 is UTC time.
Public Class frmMain
Private Sub Page_Load(sender As Object, e As EventArgs)
'Start Eve and Local Time Clocks
tmrMainTimes.Interval = 1000
tmrMainTimes.Start()
End Sub
Private Sub mnuSecuredItemEnableAccess_Click(sender As Object, e As EventArgs) Handles mnuSecuredItemEnableAccess.Click
'Show Enable Access Form (frmFirstAccess)
Dim frmFirstAccess As New frmFirstAccess()
frmFirstAccess.ShowDialog()
End Sub
Private Sub tmrMainTimes_Tick(sender As Object, e As EventArgs) Handles tmrMainTimes.Tick
''Start Local Time
'toolstripItemLocalTime.Text = Format(Now, "HH:mm:ss")
''Start Eve (UTC) Time
'toolstripItemEveTime.Text = Format(Now.ToUniversalTime, "HH:mm:ss")
dtLocalTime = DateTime.Now.ToString("HH:mm:ss")
toolstripItemLocalTime.Text = dtLocalTime
dtEveTime = DateTime.UtcNow.ToString("HH:mm:ss")
toolstripItemEveTime.Text = dtLocalTime
End Sub
Private Sub TimersToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles TimersToolStripMenuItem.Click
Dim frmTimers As New frmTimers()
frmTimers.ShowDialog()
End Sub
End Class
This works great!
The problem lies in the tools section where I am trying to give the user to initiate new timers. When I try to run a separate clock on this form, I initiate a different timer and execute the code in the same way, but the clock seems to lose a second compared to the other clocks.
Public Class frmTimers
Private Sub frmTimers_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' Start Clock Timer for Timers
TimersClocksStart.Interval = 1000
TimersClocksStart.Start()
End Sub
Private Sub TimersClocksStart_Tick(sender As Object, e As EventArgs) Handles TimersClocksStart.Tick
txtCurrRollEveClock.Text = dtEveTime
End Sub
End Class
How do I 1) fix this lag of one second between clocks and timers on multiple forms? 2) prevent it from happening again?
At most, in the application there will ever need to be twenty-five clocks/timers in five forms. At least there will need to be about ten in three forms
Related
I'm working with visual basic express 2010 to create a very simple application.
I know this is basic stuff but i need to know how to repeat the same function every X minute while the application is being left open.
This is all my code:
Public Class Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
My.Computer.Network.DownloadFile(
"http://google.co.uk/images/someimage.png", "C:/Documents and Settings/All Users/Desktop/someimage.png")
End Sub
End Class
could someone please advise on this issue?
EDIT:
This is my entire code now:
Public Class Form1
Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
My.Computer.Network.DownloadFile(
"http://new.tse.ir/en/json/MarketWatch/enMarketWatch_1.xls", "C:/temp/enMarketWatch_1.xls", "", "", False, 60, True)
End Sub
End Class
in the properties panel of the timer, I set the Enabled to true and Interval to 60000.
when i run this code, I get file downloaded but 1 second later, the file gets deleted automatically and an error pops up in the visual basic saying the operation has timed out
I tried to change the directory and still happening.
any advise would be appreciated.
Add a timer to your form in the graphical designer.
Double click the timer to generate its tick event handler code in the code window.
Move the code you want to repeat into a sub
Private Sub DownloadFile()
My.Computer.Network.DownloadFile("http://google.co.uk/images/someimage.png", "C:/Documents and Settings/All Users/Desktop/someimage.png")
End Sub
Add the command below into your timer tick event handler
DownloadFile()
Change your form.load event to
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
DownloadFile()
Timer1.Interval = x ' where x is the number of minutes*60000 because there are 60000 ticks in a minute
Timer1.Enabled = True
End Sub
The reason I've put your code into a separate sub is so that it is easily reusable in both the form.load handler and the timer.tick handler without having to write it again, and if in the future you need to change, for example the file path, you only need to remember to change it once.
Also I should add that, in the form.load handler I have included the DownloadFile method because, when the timer is enabled, it won't generate a tick until the interval has elapsed. Not at the beginning when the timer is enabled.
Also - as Plutonix suggested in comments below - If it is possible that the file to be downloaded will take longer to download than the length of the timer interval you should disable the timer in the DownloadFile sub and enable it again at the end of the sub. Like so :-
Private Sub DownloadFile()
Timer1.Enabled = False
My.Computer.Network.DownloadFile("http://google.co.uk/images/someimage.png", "C:/Documents and Settings/All Users/Desktop/someimage.png")
Timer1.Enabled = True
End Sub
Part of a program I am modifying involves communicating through a serial port using a proprietary library. Unfortunately, this library does not have the same SerialPort.DataReceived event that the System.IO.Ports namespace contains. In fact, it has no events whatsoever, however it does have two functions that can probably be used similarly:
Port.WaitForData(int time)
This function waits the given amount of time to recieve some previously specified strings over the port. It returns 1 for yes, received string, or 0 for no, did not recieve string, timed out.
Port.IsReceiveBufferEmpty()
This function returns a boolean of yes, the receive buffer is empty or no, the receive buffer contains data.
It seems to me I will have to create some thread to be continuously looping whenever the port is opened and do one of these two things:
For every loop, call WaitForData(some big number) with the specified strings it is looking for set to "", or vbCrLf, or something else that I can confirm it will recieve everytime data is sent. If it finds smoething, read it and write to a textbox. If WaitForData doesn't find anything, loop again.
For every loop, call IsReceiveBufferEmpty(), and if it isn't, read it and write to a textbox.
What the best way to go about implementing this? The first options seems potentially more efficient to me, although I know next to nothing about how these method work under the hood. Obviously I want to keep my form responsive when doing this, so how should I go about continuously looping without freezing the form but being able to read any incoming data?
Thanks for your help.
Perhaps not the most elegant solution, but you could use a BackgroundWorker to do the IO. e.g. something like this pseudo-code:
Public Class MyForm
Private _port As ProprietaryIOLibrary
Private WithEvents Worker As System.ComponentModel.BackgroundWorker
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
_port = New ProprietaryIOLibrary()
Worker = New System.ComponentModel.BackgroundWorker()
Worker.WorkerReportsProgress = True
Worker.WorkerSupportsCancellation = True
Worker.RunWorkerAsync()
End Sub
Private Sub ButtonCancel_Click(sender As Object, e As EventArgs) Handles ButtonCancel.Click
Worker.CancelAsync()
End Sub
Private Sub Worker_DoWork(sender As Object, e As DoWorkEventArgs) Handles Worker.DoWork
Do
If _port.WaitForData(1000) Then ' Adjust timeout depending on cancel responsiveness?
Dim data As String = _port.ReadDataAsString() ' ?
' Trigger the ProgressChanged event, passing the data
Worker.ReportProgress(0, data)
End If
If Worker.CancellationPending Then
Exit Do
End If
Loop
End Sub
Private Sub Worker_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles Worker.ProgressChanged
' Update the UI with the data received
' ProgressChanged is called on the UI thread, so no need to Invoke
Dim data As String = DirectCast(e.UserState, String)
TextBox1.Text &= data & vbCrLf
End Sub
Private Sub Worker_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles Worker.RunWorkerCompleted
TextBox1.Text &= "Complete!"
End Sub
End Class
Can i set time limit for a task or a code? for example if i want to show message boxes for 10 seconds and then stop or change the the message body ?
Yes, check out timers. There are three different kinds of timers:
System.Timers.Timer
System.Threading.Timer
System.Windows.Forms.Timer
Which one will work best for you will depend entirely on your specific situation. Given the limited information you provided, I suspect that the easiest way to do what you need to do is to create your own message-box-like form and place a System.Windows.Forms.Timer component on the form (you can find it in the form designer's tool box). Have the form start the timer in its own Shown event. And then show the form using the ShowDialog method.
You can start a Thread and abort it when you want:
Dim t1 As New Threading.Thread(AddressOf MyMethod)
t1.Start()
Timer1.Start()
Private Sub MyMethod()
' Do what you want
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Timer1.Enabled = False
t1.Abort()
End Sub
In a form, there is a label. It shows whether web service is connected or not at every minutes. How to code to repeat this process? Will I use the thread or timer? Please share me.
You will need a timer object in order to run the code every X minutes. Using a separate thread to check the web service only needs to be done if it will take a while to check and you want your form to remain responsive during this time.
Using a timer is very easy:
Private WithEvents timer As New System.Timers.Timer
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'Set interval to 1 minute
timer.Interval = 60000
'Synchronize with current form, or else an error will occur when trying to
'update the UI from within the elapsed event
timer.SynchronizingObject = Me
End Sub
Private Sub timer_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles timer.Elapsed
'Add code here to check if the web service is updated and update label
End Sub
I am a VB6 coder and I'm making the move to VB8 / VB.NET
I know how to wait in VB6, but my problem is that I don't know how to wait in VB8/VB.NET. I have a TextBox called textbox2 that contains the number of seconds I want to wait. I used to use wait 60 in VB6, but of course VB2008 is different.
Can anyone help me to do this?
I know this is an old question, but I thought there were so many conflicting answers and I thought the solution I use is simple and straightforward enough.
Also, I wrote this when I switched from VB6 to .net, for the same reason as OP.
Private Sub Wait(ByVal seconds As Long)
Dim dtEndTime As DateTime = DateTime.Now.AddSeconds(seconds)
While DateTime.Now < dtEndTime
Application.DoEvents()
End While
End Sub
Use this do that your UI does not hang.
For i = 1 to 300
threading.thread.sleep(i * 1000)
application.doevents
next
[edit: I re-read the question and see it was specifically asking about a TextBox named textbox2 so I've updated the answer to reflect that.]
Well, I think one answer would be to use:
System.Threading.Thread.Sleep(Int32.Parse(textbox2.Text) * 1000);
if your text box contains the number of seconds to wait. However if you aren't in a background thread, this will hang your application up for the amount of time you are waiting.
You could also do something like:
Dim StartTime As DateTime
StartTime = DateTime.Now
While (DateTime.Now - StartTime) < TimeSpan.FromSeconds(Int32.Parse(textbox2.Text))
System.Threading.Thread.Sleep(500)
Application.DoEvents()
End While
which would not hang up the UI while you wait. (Also, you could use Convert.Int32(textbox2.Text) to convert the data in the textbox.)
Oh, and in certain cases, another way you can avoid the issues with the UI locking up would be do implement a timer callback instead. (see http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx for some more detail.) To do this, you
do whatever processing you need to do before the pause
create a function that picks up processing where you left off
create a timer that calls your function afterward
Code:
Public Class MyClass
Public MyTimer As System.Timers.Timer
Public Sub OnWaitCompleted(source As Object, e As ElapsedEventArgs)
MyTimer.Stop()
MyTimer = Nothing
DoSecondPartOfProcessing()
End Sub
Public Sub DoFirstPartOfProcessing()
' do what you need to do before the wait
MyTimer = New System.Timers.Timer(Int32.Parse(textbox2.Text))
AddHandler MyTimer.Elapsed, AddressOf OnWaitCompleted
MyTimer.Start()
End Sub
Public Sub DoSecondPartOfProcessing()
' do what you need to do after the wait
End Sub
End Class
try to use a timer
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Dim interval As Integer = 0
If Integer.TryParse(Me.TextBox2.Text, interval) Then
Timer1.Enabled = True
Timer1.Interval = interval
Timer1.Start
End If
End Sub
Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
'your code here
End Sub
In the 'event of the timer ticks then implements the logic to invoke the method Timer.Stop (), but this depends on what you do.
Regards.
Use Thread.Sleep:
Thread.Sleep(60000)
Update, following comment:
To retrieve and convert the value of the text box use:
Dim sleepValue As Integer = Integer.Parse(textbox2.Text)
This will throw an exception if the value cannot be converted.
I don't know why do you want it and and why you don't use threads, but this sleep function act similar wait in vb6:
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
MsgBox("begin")
Sleep(2000)
MsgBox("end")
End Sub