Announcement

Collapse
No announcement yet.

Sleep(0) question

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Sleep(0) question

    Hi all,

    I've got a tight loop that's iterating through a SQL Result Set
    (I'm using SQLTools. Awesome product!). I'm using the sleep(0)
    function within the loop and it works great for other apps that
    are running. My problem is that I can't move around my app's
    window (the window that the loop is occuring in) while the loop
    is in process. Also, whenever another app window overlaps my
    app's window, my app's window doesn't repaint until after
    my loop is finished. How can I prevent this from happening?
    Do I need to put my looping code into it's own thread? Is
    there an easier or better way? Thanks in advance for your
    help!

    Cheers,
    Scott
    Scott Wolfington
    [url="http://www.boogietools.com"]http://www.boogietools.com[/url]

  • #2
    Scott --

    It isn't enough to simply SLEEP and let Windows do its thing. You'll need to "pump" your app's messages in order to periodically "service" your app's GUI display.

    If you're using DDT, just put DIALOG DOEVENTS inside your loop so that it executes (at least) several times per second. You could do it after every Fetch, but it's probably not necessary to do it that often. I'd create a counter variable and do DIALOG DOEVENTS every 5-100 Fetch's, depending on how responsive you want the GUI to be, vs. how fast you want the program to run.

    If you're using the API to create your GUI, instead of DIALOG DOEVENTS you'll need to call the appropriate API functions. You'll find that PeekMessage will be helpful in determining whether or not there are any pending messages that need to be processed.

    Is that enough info to get you going?

    -- Eric


    ------------------
    Perfect Sync: Perfect Sync Development Tools
    Email: mailto:[email protected][email protected]</A>

    "Not my circus, not my monkeys."

    Comment


    • #3
      Add a DoEvents inside the loop. I use the following (32-bit PB/DLL):
      Code:
      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
      ' Custom-built DoEvents.. much faster to use than DIALOG DOEVENTS in some cases
      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
      SUB NewEvents()
        STATIC Msg AS tagMsg
        IF PeekMessage(Msg, %NULL, 0, 0, %PM_NOREMOVE) THEN
          GetMessage Msg, %NULL, 0, 0
          TranslateMessage Msg
          DispatchMessage Msg
        END IF
      END SUB
      and then simply call it from inside the loop with: NewEvents

      Since this adds instructions = time to the code, one can use some
      counter and for example MOD, to avoid calling it in each cycle, like:
      Code:
      FOR I = 0 TO 100000
        IF I MOD 20 = 0 THEN NewEvents  ' call it at 0, 20 40 60, etc.
      NEXT

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

      Comment


      • #4
        Originally posted by Borje Hagsten:
        Add a DoEvents inside the loop. I use the following (32-bit PB/DLL):
        Code:
        '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
        ' Custom-built DoEvents.. much faster to use than DIALOG DOEVENTS in some cases
        '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
        SUB NewEvents()
          STATIC Msg AS tagMsg
          IF PeekMessage(Msg, %NULL, 0, 0, %PM_NOREMOVE) THEN
            GetMessage Msg, %NULL, 0, 0
            TranslateMessage Msg
            DispatchMessage Msg
          END IF
        END SUB
        and then simply call it from inside the loop with: NewEvents

        Since this adds instructions = time to the code, one can use some
        counter and for example MOD, to avoid calling it in each cycle, like:
        Code:
        FOR I = 0 TO 100000
          IF I MOD 20 = 0 THEN NewEvents  ' call it at 0, 20 40 60, etc.
        NEXT

        Whats the advantage of this over the DOEVENTS?



        ------------------
        -Greg
        -Greg
        [email protected]
        MCP,MCSA,MCSE,MCSD

        Comment


        • #5
          Borje --
          I can't understand a purpose of PeekMessage %NOREMOVE together with GetMessage.
          It's possible to use REMOVE w/o GetMessage.

          Code:
             #Compile Exe
             #Register None
             #Dim All
             #Include "Win32Api.Inc"
             
             CallBack Function DlgProc
                If CbMsg = %WM_DESTROY Then PostQuitMessage 0
             End Function
             
             Function PbMain
                Local hDlg As Long
                Dialog New 0, "Test", , , 100, 60, %WS_CAPTION Or %WS_SYSMENU To hDlg
                Control Add TextBox, hDlg, 101, "", 10, 10, 80, 15
                Control Add Button, hDlg, 102, "Button", 20, 40, 60, 15
                Dialog Show Modeless hDlg Call DlgProc
                Local Msg As tagMsg
                Do
                   If PeekMessage(Msg, %NULL, 0, 0, %PM_REMOVE) Then
                      If Msg.Message = %WM_QUIT Then Exit Do
                      If IsDialogMessage(hDlg, Msg) = %FALSE Then  ' Don't touch Tab
                         TranslateMessage Msg
                         DispatchMessage Msg
                      End If
                   Else ' Background actions
                   End If
                Loop
                MsgBox "Finished"
                
             End Function


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

          Comment


          • #6
            Semen - you're right, of course - thanks for the tip. Found it
            somewhere and have used it since, without giving it any thoughts.
            The following is a bit faster:
            Code:
            '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
            ' Custom-built DoEvents.. much faster to use than DIALOG DOEVENTS in some cases
            '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
            SUB NewEvents()
              STATIC Msg AS tagMsg
              IF PeekMessage(Msg, %NULL, 0, 0, %PM_REMOVE) THEN
                TranslateMessage Msg
                DispatchMessage Msg
              END IF
            END SUB
            Gregery, DIALOG DOVENTS is much slower. Increadibly much slower.
            Don't know why. Try the following with the code above and see
            what I mean:
            Code:
              LOCAL I AS LONG, t1 AS SINGLE, t2 AS SINGLE
             
              t1 = TIMER
              FOR I = 0 TO 4000
                  DIALOG DOEVENTS
              NEXT
             
              t2 = TIMER
              FOR I = 0 TO 4000
                 NewEvents
              NEXT
                          
              MSGBOX "DIALOG DOEVENTS: " & FORMAT$(TIMER - t1, "0.0000") & " sec." & $CRLF & _
                     "NewEvents: " & FORMAT$(TIMER - t2, "0.0000") & " sec."
            ------------------

            Comment


            • #7
              I have tested the sleep function in the ocilloscope and
              use it as a pulse to drive some stepper motor, it can't do the
              job! cause the sleep have a irregular interval!
              below are the code I use and check to be more regular in the delay interval.

              Code:
              'Routine for Doevents function in VB
              SUB DOEVENT() EXPORT
                 STATIC Msg AS tagMsg
                 IF PeekMessage(Msg, %NULL, 0, 0, %PM_REMOVE) THEN
                    TranslateMessage Msg
                    DispatchMessage Msg
                    END IF
                    END SUB
              '---------------------------------------------------------------------
              'Routine for Delay MS timming
              SUB Delay(DelayInMilliseconds AS SINGLE)
              DIM tmout AS SINGLE
              tmout = DelayInMilliseconds + timeGetTime()
              DO UNTIL timeGetTime() >= tmout
              CALL DOEVENT
              LOOP
              END SUB
              just replace Sleep() with Delay()
              I got most of my hardware run, but the turn down is the minimum delay
              is only one millisecond, anybody know how to do when I need to delay
              say half millisecond?



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

              Comment


              • #8
                > DIALOG DOVENTS is much slower. Increadibly much slower
                Borje --
                DOEVENTS is slowly, but correct.
                If you will look Task Manager, you'll see that your loop takes 100% CPU.

                On my PC, when there is no work, CPU is busy 1-2%. And DoEvents keep this level.

                I added Sleep 0 into your loop. No efect (very "fast", CPU is 100% busy).
                I changed to Sleep 1 and found
                1) Sleep 1 ... 10 = Sleep 10
                2) CPU is busy 1-2%
                3) time of execution is exactly the same as with DoEvents.

                BTW, I see one case, when usage of NewEvent will be interesting

                For example, program download file and wants to display information w/o stopping.

                Code:
                   #Compile Exe
                   #Register None
                   #Dim All
                   #Include "Win32Api.Inc"
                
                   Global hDlg As Long, StopCmd As Long
                   CallBack Function DlgProc
                      If CbMsg = %WM_DESTROY Then PostQuitMessage 0
                   End Function
                   
                   Sub NewEvent
                      Static Msg As tagMsg, n2 As Dword, n1 As Dword
                      Do
                         If PeekMessage(Msg, %NULL, 0, 0, %PM_REMOVE) Then
                            If Msg.Message = %WM_QUIT Then StopCmd = %True: Exit Do
                            If IsDialogMessage(hDlg, Msg) = %FALSE Then  ' Don't touch Tab
                               TranslateMessage Msg
                               DispatchMessage Msg
                            End If
                         Else
                            n2 = GetTickCount: If n1 = 0 Then n1 = n2
                            If Abs(n2 - n1) > 100 Then Sleep 10: n1 = GetTickCount
                            Exit Do
                         End If
                      Loop
                   End Sub
                   
                   Function PbMain
                      Dialog New 0, "Test", , , 100, 60, %WS_CAPTION Or %WS_SYSMENU To hDlg
                      Control Add TextBox, hDlg, 101, "", 10, 10, 80, 15
                      Control Add Button, hDlg, 102, "Button", 20, 40, 60, 15
                      Dialog Show Modeless hDlg Call DlgProc
                      Local i As Long, j As Long
                      For i = 1 To 1000
                         For j = 1 To 1000000
                         Next
                         If StopCmd Then MsgBox "Terminated": Exit Function
                         Control Set Text hDlg, 101, Format$(i)
                         NewEvent
                      Next
                      MsgBox "Finished"
                   End Function

                [This message has been edited by Semen Matusovski (edited July 30, 2000).]

                Comment


                • #9
                  Borge --

                  In addition to Semen's comments, I'd like to point out that your NewEvents routine does not do quite the same thing as DIALOG DOEVENTS. Your SUB processes a single message each time it is called, and DIALOG DOEVENTS processes messages until the queue is empty, so it is necessarily slightly more complex. Also, DIALOG DOEVENTS is a FUNCTION that returns a useful value, and your SUB doesn't do that, so it's understandable that, even with all other factors being equal, it would be marginally slower.

                  Finally, we can speculate but we have no way of knowing what DIALOG DOEVENTS is doing internally, to "service" the DDT engine. People are probably tired of me pointing it out, but PowerBASIC, Inc. recommends the use of the DDT function DIALOG DOEVENTS to service DDT dialogs, and recommends against using an "external" message pump such as yours.

                  -- Eric


                  ------------------
                  Perfect Sync: Perfect Sync Development Tools
                  Email: mailto:[email protected][email protected]</A>

                  "Not my circus, not my monkeys."

                  Comment


                  • #10
                    Aisin --

                    The SLEEP function (which is part of the Microsoft Windows API) is not intended for "timing" purposes. SLEEP 0 means "give up the rest of this app's time slice". SLEEP 1 means "give up the rest of this app's time slice, and keep giving up time slices until at least 1 millisecond has elapsed". Since time slices are longer than 1 ms, and many different apps may be using time slices, this results in (relatively) unpredictable results. In practice, on a typical system, the resolution of SLEEP seems to be around 10ms. Using any value between 1 and 10 will result in a 10ms delay, 11-20 will result in a 20ms delay, and so on.

                    You might want to investigate the QueryPerformanceCounter API function. As far as I know, it provides the highest resolution that is available. But keep in mind that on single-processor systems, the "multi-tasking" that is provided by Windows, Linux, etc. is an illusion. Your application only runs during its time slice, and if the system is busy running many different tasks, you haven't got a snowball's chance in shell of producing high-resolution results. If you really need to do that you will probably need to investigate the process of giving your application "real time priority" status. But that is very, very likely to interfere with other apps that are running on the system, so it is not recommended.

                    -- Eric


                    ------------------
                    Perfect Sync: Perfect Sync Development Tools
                    Email: mailto:[email protected][email protected]</A>

                    "Not my circus, not my monkeys."

                    Comment


                    • #11
                      Aisin,

                      The sleep function isn't going to be accurate. And what is worse
                      is that it will probably be different for every computer. There
                      are so many factors that will slow down the sleep function
                      or speed it up. Remember the internal clock has 18 ticks
                      per second.



                      ------------------
                      -Greg
                      -Greg
                      [email protected]
                      MCP,MCSA,MCSE,MCSD

                      Comment


                      • #12
                        Thanks everyone! Here's what I ended up doing and it seems to
                        be working pretty well. I've got another question now, but
                        I'll put that in a new post... -Scott

                        'Now let's loop through the resultset.
                        DO
                        SQL_FetchResult 1, lStmtNumber&, %NEXT_ROW
                        IF SQL_EndOfData(1, lStmtNumber&) THEN EXIT LOOP

                        'Do some stuff right here...

                        x=x+1

                        'Let's display some output.
                        IF x MOD 100 = 0 THEN
                        CONTROL SET TEXT hPage5Dlg&, %frmMain_lblRecordCount, STR$(x)
                        DIALOG DOEVENTS
                        END IF

                        SLEEP(0)

                        LOOP


                        ------------------
                        Scott Wolfington
                        [url="http://www.boogietools.com"]http://www.boogietools.com[/url]

                        Comment

                        Working...
                        X