Keeping Application running - vb.net

I am trying to keep an application open until a file appears. I am using a timer to check the FTP server every 60 seconds (file could take 13 to 15 minutes before it shows up).
The while loop works...but it takes up 50% of my CPU. Trying to figure out another way. I was looking into adding a Windows.Form and using the Application.Run(), but was wondering if the Application.Exit() would close my application.
Public Shared Function CheckStatus(ByVal TaskID As String) As Boolean
_TaskID = TaskID
'Start Timer to Check Query Status Every 10 Seconds
CheckStatusTimer.Interval = 10000
CheckStatusTimer.Enabled = True
CheckStatusTimer.Start()
'Wait for Check Query Status To Complete
While _Status = False
End While
CheckStatusTimer.Stop()
CheckStatusTimer.Enabled = False
Return _Status
End Function
Could placing the CheckStatusTimer.Stop() into completion logic section of my CheckStatusTimer_Tick() Subroutine. How can I prevent the calling function from returning until the timer is stopped?
Thanks
jlimited

The thing you are looking call is called Thread.Sleep():
While _Status = False
System.Threading.Thread.Sleep(500)
End While
This means the thread will check every 500 milliseconds (0.5s) if the Status is different.

This what you need to work with a task in background:
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2
Another thing, these lines are wrong:
CheckStatusTimer.Stop()
CheckStatusTimer.Enabled = False
You're repeating, start() method and enabled=true property perform the same thing, also stop() method and enabled=false
Here's a tutorial of how to download a file in background mode
http://msdn.microsoft.com/en-us/library/ms229675(v=vs.110).aspx

Related

How to limit the number of processes being spawned at a time?

I am working on a VB.NET Windows Forms application where the user is supposed to be able to determine how many processes the application is allowed to launch at a time.
My current method mostly works but I've noticed that occasionally the application goes over the set amount. I use two global variables for this, _ConcurrentRuns which is 0 at the start of the application, and _MaxConcurrentRuns which is set by the user.
Private _sync As new Object()
' This is called Synchronously
Private Function RunModel() As Boolean
If CancelExectuion Then Return CancelCleanup()
Do While True
SyncLock _sync
If _ConcurrentRuns < _MaxConcurrentRuns Then
Interlocked.Increment(_ConcurrentRuns)
Exit Do
End If
End SyncLock
Threading.Thread.Sleep(50)
Loop
'This is what will launch an individual process and close it when finished
ret = RunApplication(arg)
' The process has been closed so we decrement the concurrent runs
Interlocked.Decrement(_ConcurrentRuns)
Return ret
End Function
The goal is to let only one thread exit the while loop at a time, I'm not able to catch it in the debug mode however in the task manager it will occasionally go 1-3 processes over what it's supposed to use. This makes me assume that somehow multiple threads are getting inside the synclock somehow, but I have no clue how that could be happening.
I will be very grateful for any and all help that can be provided, thanks for taking the time to read my question.
So it appears that my solution works for this, I don't want to delete this question because it might be helpful to somebody else in the future.
Answer: Use better process monitoring software / set priority to high in task manager.

Vb.net How can I sleep between multiple tasks in a sub

Figured my previous attempt in doing this question was too opinion based, so I'll be more specific.
Intro:
I'm trying to best way possible sleep inbetween multiple "tasks" within a private sub, but my attempts so far have failed me.
I have 9 "tasks" being triggered by a timer timermain and a progressbar pbmain that are working together. At pbmain.value 10 task 1 is being triggered, at pbmain.value 20 task 2 is being triggered and this goes all the way up to pbmain.value 100 and at that point it sets value to 1 and then this whole process loops over and over.
The problem is that this way is not very accurate because some of the tasks take more time than the others, so I'd much rather like to somehow sleep/pause/wait a second or so between each task than use progressbar value.
This is what it looks like
Private Sub TimerMain_Tick(sender As Object, e As EventArgs) Handles TimerMain.Tick
pbMain.Increment(1)
'Channel 1
If cbc1.Checked = True Then
If pbMain.Value = 10 Then
Try
Dim fileTotal As Integer
For Each item As String In lbChannel1.Items
fileTotal += My.Computer.FileSystem.GetFiles(item.ToString, FileIO.SearchOption.SearchTopLevelOnly, (tbExt1.Text)).Count
Next
tbCount1.Text = String.Format("{0}", fileTotal.ToString)
Catch ex As Exception
lbErrors.Items.Add(String.Concat(TimeOfDay & " Error 001: ", ex.Message)) 'Error output
End Try
End If
End If
'Channel 2
'... same as above. Then channel 3, 4, 5, 6, 7, 8 and 9...
To clarify what this does and the whole purpose:
I have so called channels in my form. Each channel is a listbox with items that are paths like \server\share\folder. The code above counts files in those folders if checkbox for that specific channel is checked and gives number output to a textbox tbcount1-9. So yes, the application is monitoring files going in and out of specified folders.
My goal:
Do task 1 -> Complete task 1 and wait one second -> Move to task 2 -> repeat this all the way to task 9 and then loop
I've tried:
Perform step. Did not work well because it looped too fast and fast out of control. I removed pbmain.increment and used performstep between each task.
Thread.sleep. This caused the whole application to sleep for given amout of time instead .
Progressbar marquee mode. I tried, but couldn't figure out how to make it work like my goal.
My question:
How can I complete my goal using something else than progressbar value with a timer...?
Update
Alexander's comment answered my question
You can try with Asnyc/Await Asynchronous Programming with Async and Await
Since your task are working with IO - async/await will be best approach.
Starting new thread only for waiting result from IO is waste of resources(threads).
Private Async Function ExecuteAllAsync() As Task
While True
Await ExecuteTasksAsync()
End while
End Function
Private Async Function ExecuteTasksAsync() As Task
Dim task1 As Task = ExecuteTaskNumberOneAsync()
Await Task.Delay(1000)
Dim task2 As Task = ExecuteTaskNumberTwoAsync()
Await Task.Delay(1000)
'... and so on
'Then wait for all results
Await Task.WhenAll({task1, task2, ...})
End Function
Here is only an idea - of course code above can/must be refactored to "usable" way
Are you just looking for a simple 1 second delay? If so.
Dim Current_Time as Date=Now
While DateAdd(DateInterval.Second, 1, Current_Time)>Now
End While
Now returns the current Date and Time
So I guess your flow would be
Task1->
Delay 1 Sec->
Task 2

Delay code execution while running program

What is the best way to delay code execution in an application while the program is still running?
I've tried this method:
System.Threading.Thread.Sleep()
But the application does not display until the Sleep() has been executed and I am unsure of alternatives.
Dim t = System.Threading.Tasks.Task(Of Boolean).Run(Function() As Boolean
System.Threading.Thread.Sleep(10000)
Return True
End Function)
Dim ret = t.Result
You need to offload this to another thread, if you call sleep on the current thread then everything including the UI is going to wait until sleep has finished. There are multiple ways to achieve this including the example above.

UFT 12.0 unable to synchronize an object using .Exists property

from last few days i am trying to synchronize two objects that are dependent on each other for their execution.
EX: Object B should execute only after the completion of object A.
Now, in my scenario, the Object A is taking some time to execute, for this I need to synchronize the two objects.
The Completion of object will result in an image which will tell the user that the process is completed successfully or failed.
Below is my code:
sLoop = True
Do while sLoop
If (Browser("ABC").Page("PQR").Frame("XYZ").Image("BatchSuccess").Exist) then
msgbox "in if"
sLoop = false
Else
msgbox "in else"
sLoop = true
End If
Loop
Other Activities...
My IF condition is getting executed before it gets satisfied.
there is an image of ongoing process which the UFT is considering as the successful...
Note: there is also an image while executing the object. (observation, UFT is not able to distinguish between these 2 images)
Try to use WaitProperty method. Exist will return true when it finds Your object in app.
For example
objectA.WaitProperty(optionFromObjectSpy,someSpecificContent)
optionFromObjectSpy - innerhtml etc.
Just by looking at your code and your question, one thing pops right into my head is that you can use wait time inside your exist statement.
Like :
If B().P().Image().Exist("10") Then *'you can change the 10 second to anything you want*
'Code here
End If
Or Alternatively you could create a function that will check if readystate of the browser (assuming its IE) is 4 or not.
do while ie.readystate <> 4
Wait(1)
Loop
Call the function before doing anything with the Image object. Should work.
Try something like -
While not Browser("ABC").Page("PQR").Frame("XYZ").Image("BatchSuccess").Exist
Wait 1
Browser("ABC").Sync
Wend
'your code here after object A is synchronized
Browser("ABC").Page("PQR").Frame("XYZ").Image("BatchSuccess").Click

Console app timer to call web methods every x minutes

I am coding in VB.Net, VS 2008.
I wrote a console app that consumes 2 web methods from a web site application. I need to enhance this console app so that it launches the web methods continuously, perhaps every x minutes (during business hours), but never before the last invocation has terminated, whose duration may vary, depending on how many accounts there are to process.
Originally, I scheduled the application using Task Scheduler, but I think this doesn't prevent two invocations at the same time.
Although I have seen many posts on using timers, I haven't found exactly what I need.
So far I have:
Dim aTimer As New System.Timers.Timer()
AddHandler aTimer.Elapsed, AddressOf TriggerWebMethods
' Set the Interval to 10 minutes:
aTimer.Interval = 1000 * 60 * 10 '(1 second * 60 = 1 minute * 10 = 10 minutes)
aTimer.Enabled = True
aTimer.AutoReset = True
When should Timer.Elapsed be used vs. Timer.Tick?
What is the difference between Timer.Enabled vs Timer.Start, and should I be selecting just one?
I would like the 2nd web method to kick off when the first one is done.
I'd like to keep this as simple as possible. Thank you for all help.
If you are dealing with a System.Timers.Timer, then you'd only have the Elapsed event available. If a System.Windows.Forms.Timer, then you'd use the Tick event. You're not writing a WinForms app so you would be using the System.Timers.Timer.
Personally, I would only use the Enabled property to see if the timer has been started. I wouldn't use it to start or stop it. Using the Start() or Stop() method makes it very clear what's happening to the timer.
If your web methods execute synchronously, you could just call them one after the other in your TriggerWebMethods() method. The second will not be called until the first completes.
Sub TriggerWebMethods(source As Object, e As ElapsedEventArgs)
FirstWebMethod()
SecondWebMethod()
End Sub
If asynchronously, you'd have to register a callback on the first web method to execute the second when it completes. In VB, I believe you can use the second directly as the callback, depending on how you make the asynchronous call. (Sorry, my VB is very rusty now so might not be 100% correct syntax)
Sub FirstWebMethod()
' ...
End Sub
Sub SecondWebMethod()
' ...
End Sub
Sub TriggerWebMethods(source As Object, e As ElapsedEventArgs)
Dim first As Action = AddressOf FirstWebMethod
first.BeginInvoke(AddressOf SecondWebMethod, first)
End Sub
Just to add a little to Jeff M's answer. The Timer.Elapsed Event has the following note.
If the SynchronizingObject property is null, the Elapsed event is
raised on a ThreadPool thread. If the
processing of the Elapsed event lasts
longer than Interval, the event might
be raised again on another ThreadPool
thread. In this situation, the event
handler should be reentrant.
Since you're in a Console app you can either hand roll you own SynchronizingObject or you can set the AutoReset to False, and change your TriggerWebMethods to have a start at the end. You may even want to offset the interval to take into consideration the amount of processing time.
e.g.
Dim start As Date = Now
'do stuff
Dim ts As TimeSpan = Now - start
Dim i As Integer = (1000 * 60 * 10) - ts.TotalMilliseconds
Dim aTimer As Timers
aTimer.Interval = i