"Counter" on form quits counting when form loses focus

Zardlord

Member
Joined
Mar 14, 2009
Messages
16
Programming Experience
1-3
Most of my experience in Visual Basic programming is in VBA. I'm currently trying to build a VB.NET Windows application that basically consists of a form that has one button and one label. When the button is clicked, the label should serve as a "counter" that counts from 0 to infinity until the user closes the window with the "x" button.

I do this by putting a loop with a sleep statement in the onclick sub. The loop iterates the integer that is displayed in the label and does a "Me.Refresh".

The problem is when the window loses focus. When it loses focus (when I click off of it), the counter stops. Even when I click back on it, the counter doesn't resume. If anyone can tell me what I'm doing wrong, I'll be grateful.
 
This is gonna be embarassing :)

Here is the code:

'----------------------------------------------------
Imports System.Threading

Public Class Form1

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

While (True)

Thread.Sleep(1000)

lblCounter.Text = lblCounter.Text + 1

Me.Refresh()

End While

End Sub

End Class
 
The while loop is what keeps the value of that integer (really the text of the label) counting upwards from zero every second. Without the while loop, the click event will just increase the initial value of the label (set to 0 by default) to 1 and then end. I'd have to keep clicking the button to get it to increment by one each time, which defeats the purpose.
 
You dont want to create an endless loop....

I would say to put your counter code in a time but Im not sure what the purpose of constantly counting is for, specially if you want your program to become inactive but still keep counting....

If your trying to judge time spans, there are much better methods such as storing the start time and comparing it with the end time of the application.
 
So you mean use a "timer" and make the value of the label the difference between the start time (when the button is clicked) and the current time? Then how do I get the label to redraw or whatever?
 
No if your comparing time periods, you wont need a counter or timer.
What are you trying to accomplish?
 
OK, the actual thing I'm doing is creating a form that has a "Send" button on it. When the user hits "Send", a file will be sent to a network location. Then, when that same file gets moved by another process on that machine it's on to a different directory, MY application will detect that it has been moved and it will copy the file back to where it was originally at. The counter is to let the user know how long they have been waiting.
 
Since you seem to know when the process first starts and the process ends, you can compare just those things when it does end and then show the elapsed time. This differs if you want a visibile timer updating every second while the wating process is occuring. (I usually just run some type of animated gif to show progress though.)

Actually the only difference is if your checking and displaying the results once at the end opposed too each second while your waiting.

Type in StopWatch in the help file, it has a downloadable example of a stop watch program If you want something that visibly updates each second, I would call that part in a timer, if not just call it once when the process is completed.
 
Last edited:
This was originally a VBA form that users call as a macro. It closes the document that the user has open and sends the file to a network location A. A service that runs on the machine that A is on detects the arrival of the file and runs a process on it, saves it, and moves it to a directory (also shared on the network) B. When the file arrives in B, the original VBA macro (the form) detects that it has arrived at B and copies it back over.

I decided to port this code over to a VB.NET project because by doing this within a VBA macro, the application that the macro is run in is seized up (the form has the counter running). Therefore, I want the VBA macro to just kick off this new VB.NET Windows application, and while the Windows app sends this file off to be processed and waits for it to appear in location B, the user can go about his/her work.

I was monitoring directory B from within the endless while loop like so:

While(isDone = False)

lblCounter.Text = lblCounter.Text + 1

Thread.Sleep(1000)

If( System.IO.File.Exists(pathToFileInB) ) then

isDone = true

End If

Loop


I just typed that code up from memory so there may be an error, but I definitely had this working in VBA (using the equivalent VBA commands), the problem is that by using VBA the application that the VBA macro was launched from becomes useless.
 
Also, instead of the code above I've been considering using a FileSystemWatcher instead of using that "File.Exists" command. Therefore the click event code would go

Public Class Form1

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

'===================
' All sorts of junk here
'===================

Try
objWatcher = New FileSystemWatcher(WatchDirectoryPath, "*.*")
Catch ex As Exception
System.IO.File.AppendAllText(LogFilePath, "Couldn't create FileSystemWatcher" & vbNewLine)
End
End Try

objWatcher.NotifyFilter = NotifyFilters.FileName
AddHandler objWatcher.Created, AddressOf OnNewFileCreated
objWatcher.EnableRaisingEvents = True

'Something here to make the counter label thing work

'===================
' All sorts of junk here
'===================

End Sub

-------------------------------------------------------

Sub OnNewFileCreated(ByVal objSource As Object, ByVal objEvent As FileSystemEventArgs)

'===================
' All sorts of junk here
'===================

End Sub

End Class
 
OK, I've realized how ass-backwards my original design was. I've gotten this to work fine using a Timer and a FileSystemWatcher here is the code

VB.NET:
Imports System.IO

Public Class Form1

    Private objWatcher As FileSystemWatcher
    Private WatchDirectoryPath As String = "C:\Temp\WatchDir"
    Private LogFilePath As String = "C:\Temp\myLog.log"

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Timer1.Interval = 1000
        Timer1.Start()

        '=======================
        ' All sorts of junk here
        '=======================

        Try
            objWatcher = New FileSystemWatcher(WatchDirectoryPath, "*.*")
        Catch ex As Exception
            System.IO.File.AppendAllText(LogFilePath, "Couldn't create FileSystemWatcher" & vbNewLine)
            End
        End Try

        objWatcher.NotifyFilter = NotifyFilters.FileName
        AddHandler objWatcher.Created, AddressOf OnNewFileCreated
        objWatcher.EnableRaisingEvents = True

        'Something here to make the counter label thing work

        '=======================
        ' All sorts of junk here
        '=======================

        Button1.Enabled = False

    End Sub

    Sub OnNewFileCreated(ByVal objSource As Object, ByVal objEvent As FileSystemEventArgs)

        System.IO.File.AppendAllText(LogFilePath, "File arrived:" & objEvent.Name & vbNewLine)
        Timer1.Stop()
        lblCounter.Text = "DONE"

    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

        lblCounter.Text = lblCounter.Text + 1
        Me.Refresh()

    End Sub
End Class
 
The timer is set for one second but to be honest the timer isnt that accurate. You might be much better using the stopwatch elapsed methods to show time past in it.
 
Well since I'm using the tick event of the timer in increase the value of the "counter" and refresh the form, I'm lost as to how I would achieve the same thing with a Stopwatch object. Is there an event associated with the Stopwatch that I can add an event handler to in order to do this?
 
Back
Top