Solved

Out of Points - Take Pity, Easy Anyways

Posted on 1999-01-27
10
146 Views
Last Modified: 2010-05-03
Why does the following Form not work?
It's supposed to flash the Label On/Off.

The problem is this:
I have some Text Processing  routines that come after starting a timer. After the routines the Timer is disabled.
The routines take about 30 seconds or more.
But the timer never does anything!
Just like below!
Does this mean the Timer only works when the program is
idle?


Private TimeNum As Integer

Private Sub Command1_Click()
Timer1.Enabled = True

Here:
If TimeNum < 2 Then GoTo Here  ' Loop to simulate processing  ' The Form will loop here forever.
 ' Timer1 is never activated so TimeNum can't advance!

End Sub

Private Sub Form_Load()
TimeNum = 0

End Sub

Private Sub Timer1_Timer()
TimeNum = TimeNum + 1
If TimeNum = 1 Then Label1.Visible = True
If TimeNum = 2 Then Label1.Visible = False
If TimeNum = 3 Then
 Label1.Visible = True
 TimeNum = 0
End If


End Sub
0
Comment
Question by:jgore
  • 4
  • 2
  • 2
  • +1
10 Comments
 
LVL 2

Expert Comment

by:sbmc
ID: 1470976
Replace your label with:

Do while TimeNum < 2
    DoEvents
Loop

This will allow the timer to do something
0
 

Author Comment

by:jgore
ID: 1470977
Sorry, I guess I wasn't very clear. Thanks for trying though!

The above was just an example.
The actual events to do are shown below and take about 2 minutes!
(they are really kinda irrelivent here).

The main thing is:
During this 2 minutes nothing else on any form will work!
I'm really just trying to blink a label off/on that says "Processing" during
this 2 minutes of waiting hell. I don't wan't the user to think that the program
has crashed!
1) Timer won't work.
2) Timer on another form won't work! (other form only half loads
before the processing routines catch hold and halt it).
3) Nothing works during the 2 minutes while it is processing.

I always thought Windows was multitasking, or is it just
Visual Basic that isn't?   ;-)

I just wanted to do something else (blink a label) while all this processing
is taking place. I thought VB5 would run Concurrent forms. But I guess not.



' These don't mean anything to you, but it's alot of Processing.
' Takes 2 minutes to finish and can't be done in small peices.
'  It's like a locamotive that stops everything else in it's tracks!
'  It's an automatic decode process.

     Kill ("temp.log")        ' Delete Old File
     Call GetKeyFiles      ' Load all Key file Names in Array, Get KeyfileNum
     Call LoadCommon    ' Load Common Words into Array, Get CommonNum
   
     For i = 1 To KeyFileNum                         ' Loop for All Keys
     Call LoadKey(Main.Label3.Caption & KeyFiles(i)) ' Load Key Dir & Path
     Call CheckKey                        ' Check if Key is missing chars
     Call Decode(Main.Label7.Caption, "temp.txt")  ' Decode text to Temp.txt
     Call CommonCheck               ' Check for Common Words for Success
     Next i


P.S. I could make the label blink in-between the routines but that wouldn't be
very nice looking. I wanted a timer event of some kind to do it at regular intervals.
But Timers quit working when the CPU is tied up with other things, I guess.    
0
 
LVL 2

Expert Comment

by:wpd
ID: 1470978
It is your main procedure that is preventing the timer from executing. Windows _is_ multitasking, but since there's no way to create a new thread in VB... as long as your proc runs, nothing else is going to happen, unless you call "DoEvents" in your FOR loop so that the timer gets a little CPU time. You may also blink the control from the loop itself.
0
 

Author Comment

by:jgore
ID: 1470979
I peppered my For Loop with DoEvents (about 10 of them) , it did help a little.
But, not much. It was still very slow and the label couldn't blink right.

However, you showed me a path.
The VB5 Online books mentioned ActiveX and some other stuff that arn't
affected by my main program. Perhaps I'll try that.
Seems like a long way to go for a blinking label   ;-)
0
 
LVL 2

Expert Comment

by:wpd
ID: 1470980
You'll need some piece of code that will run on its own thread. Mightn't be easy, though, especially if your FOR loop is CPU intensive. Chances are your blinking text won't appear very cheerful :( Again, why don't you make it blink from the loop itself ? At least you'll get some control on when to hide/show the control, etc...
0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 2

Accepted Solution

by:
sbmc earned 0 total points
ID: 1470981
You really need to place your DoEvents in the most CPU intensive routines and build logic into your other event processing to prevent them from re-executing eg

In Module

Public ProcessingNow as Boolean


Private Sub Command1_Click
   If ProcessingNow then ' User has already pressed button
      exit sub           ' so get out
   Else
      ProcessingNow = True
   End If
   'Calls to other functions go here

   Call DoSomeHardWork(UseAShovel)
   ProcessingNow=False      'Reset the processing flag so user
                            'can click Command1 again (if req)
End Sub

Private Sub DoSomeHardWork(UseThisTool)
    a=1
    For i=1 to 100000
      a=a*3.1417+b*sin(i mod 90)
      DoEvents
    Next I
End Sub

That was a lot of hard work for 3 point !!  
0
 
LVL 4

Expert Comment

by:anzen
ID: 1470982
Before beginning to fill up Your code with "doevents" try this way:

Start an ActiveX EXE project, add a form (frmTicks) to it and a timer (tmrTicks) to the form, next in the main (public) class module add some code like this:

' General
Private mfrmTicks   As frmTimer  ' the form containing our timer
Private WithEvents mtmrTicks As Timer ' the actual timer

Public Event Tick()

Private Sub Class Initialize()
   Set mfrmTicks = New frmTicks
   Set mtmrTicks = mfrmTicks.tmrTicks
   mtmrTicks.Enabled = False
End Sub

Private Sub Class Terminate()
   On Local Error Resume Next
   Set mtmrTicks = Nothing
   Set mfrmTicks = Nothing
End Sub

Public Property Let DoTicks(ByVal bYesNo As Boolean)
   With mtmrTicks
     .Interval = 1000
     .Enabled = bYesNo
   End With
End Property

Private Sub mtmrTicks_OnTimer()
   Static bBusy As Boolean
   Dim lTemp As Long

   If bBusy = False Then
      bBusy = True
      RaiseEvent Tick()
      lTemp = DoEvents()
      bBusy = False
   End If
End Sub

then compile the ActiveX EXE and use it instead of the Timer, this way the timer runs into a separate thread and isn't locked up by the program loops

0
 
LVL 4

Expert Comment

by:anzen
ID: 1470983
Before beginning to fill up Your code with "doevents" try this way:

Start an ActiveX EXE project, add a form (frmTicks) to it and a timer (tmrTicks) to the form, next in the main (public) class module add some code like this:

' General
Private mfrmTicks   As frmTimer  ' the form containing our timer
Private WithEvents mtmrTicks As Timer ' the actual timer

Public Event Tick()

Private Sub Class Initialize()
   Set mfrmTicks = New frmTicks
   Set mtmrTicks = mfrmTicks.tmrTicks
   mtmrTicks.Enabled = False
End Sub

Private Sub Class Terminate()
   On Local Error Resume Next
   Set mtmrTicks = Nothing
   Set mfrmTicks = Nothing
End Sub

Public Property Let DoTicks(ByVal bYesNo As Boolean)
   With mtmrTicks
     .Interval = 1000
     .Enabled = bYesNo
   End With
End Property

Private Sub mtmrTicks_OnTimer()
   Static bBusy As Boolean
   Dim lTemp As Long

   If bBusy = False Then
      bBusy = True
      RaiseEvent Tick()
      lTemp = DoEvents()
      bBusy = False
   End If
End Sub

then compile the ActiveX EXE and use it instead of the Timer, this way the timer runs into a separate thread and isn't locked up by the program loops

0
 

Author Comment

by:jgore
ID: 1470984
anzen:

The following two routines show in red and thus don't work:
They just stay in the declarations section. Moving them doesn't help.
I'll work on it.

 Private Sub Class Initialize()
         Set mfrmTicks = New frmTicks
         Set mtmrTicks = mfrmTicks.tmrTicks
         mtmrTicks.Enabled = False
      End Sub

      Private Sub Class Terminate()
         On Local Error Resume Next
         Set mtmrTicks = Nothing
         Set mfrmTicks = Nothing
      End Sub


sbmc:
You right, if I had the points I'd up-it to 300! Sorry.
I really thought it was a simple question. I didn't know the VB5 Timer
was this lame (only works in idle). Who knew?  ;-)

I really like your ProcessingNow variable. Keeps dumb users (me) from hitting
the button twice and having to sit though the routines twice as result!
But, I still don't think DoEvents will help.  The DoSomeHardWork stuff in my program
uses at least 20 routines or more, and are very intertwined. It would be hard, and
messy to add that many DoEvents. I was hopeing for a more elegant solution.

I feel really foolish for having even asked the question now!
I really thought it would be easier.

Everyone:
ActiveX OCX controls don't work either. It has to be an EXE, or even a
seperate program (I'm tempted to do it in old DOS Turbo Basic which makes
EXE's. Easy to make, small 30K, and I could just shell to it and run concurrently.
But, thats too easy and a bit hokey).
I think I'll work on the ActiveX EXE and see what happens.
0
 

Author Comment

by:jgore
ID: 1470985
In case anyone is weird enough to read all this:

I have made an ActiveX EXE called XTimer which does nothing but
load and blink the words  "Processing" in red and blue in a small window.
It is independent of your program and isn't effected by your programs
CPU usuage!
It could be used for lots of things that need an independent timer.
I will post it w/source on my Web Page ,in a day or so, at:
http://members.tripod.com/~j_gore/
If nothing else it's a good example of ActiveX EXE, really a hacked version
of the CoffeeMonitor sample that comes with VB5.
Problem has been resolved!  Thanks all !
jgore@home.com
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Have you ever wanted to restrict the users input in a textbox to numbers, and while doing that make sure that they can't 'cheat' by pasting in non-numeric text? Of course you can do that with code you write yourself but it's tedious and error-prone …
This article describes some techniques which will make your VBA or Visual Basic Classic code easier to understand and maintain, whether by you, your replacement, or another Experts-Exchange expert.
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now