VB.NET Timer question - windows

I wrote a VB.NET Windows Service, which works fine. I have only one issue with it. I want the service to execute on the half hour and top of the hour marks (e.g. 9:00, 9:30, 10:00, 10:30, 11:00, etc etc etc). I am using the following code:
Protected Overrides Sub OnStart(ByVal args() As String)
' Add code here to start your service. This method should set things
' in motion so your service can do its work.
Dim oCallBack As New TimerCallback(AddressOf TimedEvent)
oTimer = New System.Threading.Timer(oCallBack, Nothing, 300000, 300000)
EventLog.WriteEntry("CCFinalizeService has begun successfully." , _
System.Diagnostics.EventLogEntryType.Information)
End Sub
This code works, however, if the service starts at, say, 10:15, then it executes at 10:15, 10:45, 11:15, 11:45. How do I make it so it always executes on the 30 minute and top of the hour marks?

You could change it so that, at startup, it figures out the time required to go to a half hour increment based off the current time. Basically, your first timer would be <300000, then switch to every 300000.
Alternatively, you might want to consider using the Windows Task Scheduler instead of doing this as a service. The task scheduler lets you specify specific times to run an application.

You just need to modify the dueTime parameter in the Timer creation method
Dim now As Date = DateTime.Now
Dim dueTime As Integer ' milliseconds to the next half-hour
dueTime = 1800000 - (now.Minute Mod 30) * 60000 - now.Second * 1000 - now.Millisecond
oTimer = New System.Threading.Timer(oCallBack, Nothing, dueTime, 1800000)

Probably the easiest solution would be to test, at service startup, the current time, via the Date.Now property. You can then use a second timer to start the first timer, but set the Interval on the second timer to fire only at the next 1/2 hr or full hour mark.
Alternately, in your startup routine, have an infinite while loop that tests to see if the current time is on your mark. If not, System.Threading.Thread.Sleep(1000) and test again.
Good luck!

Maybe something like this??
If Now.Minute <> 0 Or Now.Minute <> 30 Then
Thread.Sleep((30 - Now.Minute) * 60 * 1000)
End If

Related

How do I wait for a worker process to finish but also limit it's time to do so?

I am writing a Windows service in VB.Net that will go out to some devices and data log points of information. I am using a Background Worker to do that so the service itself is still responsive. I have a timer that runs every second and checks the minute component of the current time. Each time the minute component changes I check which devices need to be checked, some are every minute, some every 5, some every 10, etc. These processes can take a few seconds or over a minute (I only rerun the worker if it's not already running and log a error if the last process took longer then the data retrieval interval).
In my OnStop event for the service I want to make sure the workers all close down. I call CancelAsync on the worker and the worker checks for cancellation to hopefully exit cleanly (i.e., check cancelation, if false retrieve data, save data into database, loop).
My problem is I don't want to use a sleep statement as it will lock everything but I also don't want the service to never shut down. So for example I have this currently:
Protected Overrides Sub OnStop()
' Add code here to perform any tear-down necessary to stop your service.
My.Application.Log.WriteEntry("ServiceABC shutting down for device " & DeviceID)
ServiceTimer.enable = false
If DataRetrievalBackgroundWorker.IsBusy Then
DataRetrievalBackgroundWorker.CancelAsync()
Dim x As Integer = 0
While ((DataRetrievalBackgroundWorker.IsBusy) Or (x < 15))
Threading.Thread.Sleep(1000)
x += 1
End While
End If
End Sub
This should work since the background worker is on another thread correct? Is there a better way to handle this?
You're close, if you don't want to Sleep(1000) and lock things up, do a Sleep(1).
'Dim x As Integer = 0
'While ((DataRetrievalBackgroundWorker.IsBusy) Or (x < 15))
' Threading.Thread.Sleep(1000)
' x += 1
'End While
Dim T As Date = Now.AddSeconds(15)
While DataRetrievalBackgroundWorker.IsBusy Or Now() < T
Threading.Thread.Sleep(1)
Application.DoEvents()
End While

Loop is taking around 10 minutes in vb

For Each drow As DataGridViewRow In DgvItemList.Rows
drow.Cells("strSrNo").Value = drow.Index + 1
Next
I have more than 3500 records in DgvItemList. I just give to numbering to that records but it tool 9 to 10 minutes for that.
How to reduce this time ?
Two things. Each time you change the value, it could cause the DataGridView to update, so just before your loop, add
DgvItemList.SuspendLayout
and after the loop, add
DgvItemList.ResumeLayout
You could also change the loop to a Parallel.For loop, so your final code would be something like
DgvItemList.SuspendLayout
Parallel.For(0, DgvItemList.Rows.Count, Sub(index As Integer)
DgvItemList.Rows(index).Cells("strSrNo").Value = DgvItemList.Rows(index).Index + 1
End Sub)
DgvItemList.ResumeLayout
Try it with just the Suspend and Resume layout first. You may not get a vast amount of improvement from the parallelization. Worth a go though.

While Recording in Squish using python, how to set the application to sleep for sometime between 2 consecutive activities?

I am working on an application where there are read only screens.
To test whether the data is being fetched on screen load, i want to set some wait time till the screen is ready.
I am using python to record the actions. Is there a way to check the static text on the screen and set the time ?
You can simply use
snooze(time in s).
Example:
snooze(5)
If you want to wait for a certain object, use
waitForObject(":symbolic_name")
Example:
type(waitForObject(":Welcome.Button"), )
The problem is more complicated if your objects are created dynamically. As my app does. In this case, you should create a while function that waits until the object exists. Here, maybe this code helps you:
def whileObjectIsFalse(objectID):
# objectID = be the symbolic name of your object.
counter = 300
objectState = object.exists(objectID)
while objectState == False:
objectState = object.exists(objectID)
snooze(0.1)
counter -= 1
if counter == 0:
return False
snooze(0.2)
In my case, even if I use snooze(), doesn't work all the time, because in some cases i need to wait 5 seconds, in other 8 or just 2. So, presume that your object is not created and tests this for 30 seconds.
If your object is not created until then, then the code exits with False, and you can tests this to stop script execution.
If you're using python, you can use time.sleep() as well

Visual Basic: How to use timer properly

I'm trying to write a simple program that could perform some tasks at specified time.
Here's what I have:
If (TimeOfDay = "06:12:50") Then
MsgBox(TimeOfDay)
End If
If (TimeOfDay = "06:13:58") Then
MsgBox(TimeOfDay)
End If
This code is placed inside Timer1_Tick, I set time interval - 1000 and it works OK, I get TimeOfDay value in MsgBox when current time is equal to my specified time.
But what should I do to make it work dynamically? For example: I want to type TIME value via TextBox and pass it to Timer1_Tick I need to do it as many times as I want so everytime current time matches with my specified hour,minute,second it would work, but I don't know where I have to put my code, because if I place code in while loop and in Time_Ticker1 it runs while loop every second and UI crashes immediately.
Thank you in advance for your help!
Have you considered setting a Windows Scheduled event of MSG to yourself using the AT command line? The operating system timer/scheduler, dialog, storage and queue are already there and the MSG can optionally be dismissed if there is no one to receive it within a set amount of time. Example to send the time at 06:12:15 run the following into a command shell.
AT 06:12:15 msg %USERNAME% It is 06:12:15 am

Time Delay in VBScript

i want to introduce a 3 hour delay between two consecutive lines in my VB script code.
I am using the following code snippet for this:
WScript.Sleep 10800000
But I think the code is stopping for a long time, much more than 3 hours. I used 10800000 as i read time is given in milliseconds.
Please let me know my mistake and the correct way to achieve this.
Thank You!
Try something like this:
timeout = DateAdd("h", 3, Now)
Do Until Now > timeout
WScript.Sleep 200
Loop
Important This solution was provided because question was tagged excel-vba at the beginning.
I will give you different option. I imagine you have something like this at the moment:
Sub MyCurrentSub()
Dim A
A = 10
'wait 3 hour here and...
'...after 3 hours do other part of the sub
MsbBox A
End Sub
During waiting time, even if you use different option to wait (like Do...Loop) your Excel application will be limited, at least partially will not work as usually.
I would do it in this way, by creating and calling different Sub at the right moment:
Public A
Sub MyNewSub_1()
A = 10
Appication.OnTime Now + TimeValue("03:00:00"), "MyNewSub_2"
End Sub
'now you can use your Excel as usually...
Sub MyNewSub_2()
MsgBox A
End Sub
You will get the same result, Excell will be free for you to use for 3 hours during waiting time. The only think you need to remember is to- DO NOT QUIT APPLICATION. If you Quit Excel it will 'forget' to call MyNewSub_2.

Resources