Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

Processing 2000 files with threads

Collapse
This topic is closed.
X
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    PBWin Processing 2000 files with threads

    Updated by Jim Fritts on 2020-AUG-18
    Designed to run on Windows 10 2004
    Platform: PBWIN10 and J. Roca includes
    To use this program as is you will need to download Gary Beene's sample files from here.

    Replace his Threads.bas with this app.
    As a comparison Gary's unmodified code ran 6.1 minutes for 2000 files.
    My modified version uses 11 threads and ran 12.4 seconds for 2000 files.

    Comments here please:

    Code:
    'Compilable Example:
    #COMPILE EXE "threads.exe"
    #DIM ALL
    
    'Updated by Jim Fritts on 2020-AUG-18
    'Designed to run on Windows 10 2004
    'Platform: PBWIN10 and J. Roca includes
    'To use this program as is you will need to download Gary Beene's sample files from
    'http://www.garybeene.com/files/threads.zip
    'Replace his Threads.bas with this app.
    'As a comparison Gary's unmodified code ran 6.1 minutes for 2000 files.
    'My modified version uses 11 threads and ran 12.4 seconds for 2000 files.
    
    'Comments here please:
    'https://forum.powerbasic.com/forum/user-to-user-discussions/programming/798049-effect-of-multiple-threads?p=798357#post798357
    
    #DEBUG ERROR ON
    #DEBUG DISPLAY ON
    
    %Unicode = 1
    #INCLUDE "Win32API.inc"
    
    #RESOURCE ICON logo, "index.ico"
    
    ENUM Equates SINGULAR
       IDC_Stop = 1500
       IDC_Start
       IDC_Next
       IDC_Finished
    END ENUM
    
    GLOBAL hDlg          AS LONG
    GLOBAL StopAction    AS LONG
    GLOBAL URLsPerThread AS LONG
    GLOBAL ThreadsCount  AS LONG
    GLOBAL hThread01, _
           hThread02, _
           hThread03, _
           hThread04, _
           hThread05, _
           hThread06, _
           hThread07, _
           hThread08, _
           hThread09, _
           hThread10, _
           hThreadStore  AS DWORD
    GLOBAL URLS()     AS STRING    'file name array shared between main app and storage thread
    GLOBAL StartTime  AS STRING
    
    GLOBAL qFreq      AS QUAD
    GLOBAL qStart     AS QUAD
    GLOBAL qStop      AS QUAD
    
    GLOBAL StartPT    AS LONG
    GLOBAL NextPT     AS LONG
    
    GLOBAL SequencePT AS LONG
    GLOBAL giWipedFolder AS LONG
    GLOBAL StoreIt    AS LONG
    
    GLOBAL giThread01 AS LONG
    GLOBAL giThread02 AS LONG
    GLOBAL giThread03 AS LONG
    GLOBAL giThread04 AS LONG
    GLOBAL giThread05 AS LONG
    GLOBAL giThread06 AS LONG
    GLOBAL giThread07 AS LONG
    GLOBAL giThread08 AS LONG
    GLOBAL giThread09 AS LONG
    GLOBAL giThread10 AS LONG
    GLOBAL giThreadStore AS LONG
    
    GLOBAL File01() AS STRING    'unshared between modification threads
    GLOBAL File02() AS STRING    'unshared between modification threads
    GLOBAL File03() AS STRING    'unshared between modification threads
    GLOBAL File04() AS STRING    'unshared between modification threads
    GLOBAL File05() AS STRING    'unshared between modification threads
    GLOBAL File06() AS STRING    'unshared between modification threads
    GLOBAL File07() AS STRING    'unshared between modification threads
    GLOBAL File08() AS STRING    'unshared between modification threads
    GLOBAL File09() AS STRING    'unshared between modification threads
    GLOBAL File10() AS STRING    'unshared between modification threads
    
    GLOBAL PROCESSIT()  AS LONG  'control array shared between modification threads
    GLOBAL FINISHEDIT() AS LONG  'control array shared between modification threads
    
    GLOBAL giAppRunning AS LONG
    GLOBAL FileTotal    AS LONG
    GLOBAL BreakTime    AS LONG
    
    FUNCTION PBMAIN() AS LONG
       LOCAL i    AS LONG
       LOCAL Time AS TIMECAPS
    
       TimeGetDevCaps ( Time, SIZEOF(Time) )
       timeBeginPeriod (Time.wPeriodMin)
       SLEEP 16
    
       DIM PROCESSIT(1 TO 10) AS LONG
       DIM FINISHEDIT(1 TO 10) AS LONG
    
       FileTotal = 2000
       DIM File01(1 TO FileTotal/10) AS GLOBAL STRING
       DIM File02(1 TO FileTotal/10) AS GLOBAL STRING
       DIM File03(1 TO FileTotal/10) AS GLOBAL STRING
       DIM File04(1 TO FileTotal/10) AS GLOBAL STRING
       DIM File05(1 TO FileTotal/10) AS GLOBAL STRING
       DIM File06(1 TO FileTotal/10) AS GLOBAL STRING
       DIM File07(1 TO FileTotal/10) AS GLOBAL STRING
       DIM File08(1 TO FileTotal/10) AS GLOBAL STRING
       DIM File09(1 TO FileTotal/10) AS GLOBAL STRING
       DIM File10(1 TO FileTotal/10) AS GLOBAL STRING
    
       DIALOG DEFAULT FONT "Tahoma",12, 0
       DIALOG NEW PIXELS, 0, "Process 2000 Threads",,,600,70, %WS_OVERLAPPEDWINDOW TO hDlg
       DIALOG SET ICON hDlg, "logo"
       CONTROL ADD BUTTON, hDlg, %IDC_Start,"Start", 10,10,70,25
       CONTROL ADD BUTTON, hDlg, %IDC_Stop,"Stop", 90,10,70,25
    
       DIALOG SHOW MODAL hDlg CALL DlgProc
    END FUNCTION
    
    CALLBACK FUNCTION DlgProc() AS LONG
       SELECT CASE CB.MSG
          CASE %WM_INITDIALOG
              IF ISFALSE ISFOLDER("threads_formatted") THEN MKDIR "threads_formatted"
              'Settings_INI "get"
              CALL LoadURLs      '1 to FileTotal
              QueryPerformanceFrequency qFreq
              giAppRunning = 1
              StartPT = 1
              BreakTime = 10
              CALL Load10Files
    
          CASE %WM_DESTROY
              winbeep(3000, 75)
              giAppRunning = 0
              Settings_INI "save"
    
          CASE %WM_COMMAND
              SELECT CASE CB.CTL
    
                  CASE %IDC_Stop     : StopAction = 1
                  CASE %IDC_Start    : ThreadsCount = 10  : URLsPerThread = 1  : ProcessFiles
                  CASE %IDC_Next
                      IF FileTotal >= 2000 THEN
                          IF StopAction = 0 AND giAppRunning = 1 AND StartPT < 2000 - 10 THEN   '< for all 2000 files
                              'CALL ShowData
                              StartPT = NextPT
                              CALL Load10Files
                              'call ShowData
                              CALL SendFireCommand
                          ELSE
                              StoreIt = 1  'signal thread to store files
                          END IF
                      END IF
    
                  CASE %IDC_Finished
                      'there will be a small time delay here
                      QueryPerformanceCounter   qStop
                      DIALOG SET TEXT hDlg, "Processing Threads ...      " + _
                                    FORMAT$(UBOUND(URLS), "##,##0") + "    " + _
                                    Legend + "   " + StartTime + "   " + _
                                    TIME$ + "    " + FORMAT$((qStop-qStart)/qFreq,"###.0") & "s"
    
                      ? "Success!"
                      IF SequencePT = FileTotal/10 THEN EXIT SELECT
    
                      IF FileTotal > 2000 THEN
                          NextPT = 1
                          StartPT = NextPT
                          CALL Load10Files
                          'call ShowData
                          CALL SendFireCommand
                      END IF
              END SELECT
       END SELECT
    END FUNCTION
    
    SUB ShowData
      ? "URL 1=" & URLs(1) & $CRLF & _
        "URL 2000=" & URLs(2000) & $CRLF & $CRLF & _
        "Temp String 1 Length=" & STR$(LEN(File01(SequencePT))) & $CRLF & _
        "Temp String 2 Length=" & STR$(LEN(File02(SequencePT))) & $CRLF & _
        "Temp String 3 Length=" & STR$(LEN(File03(SequencePT))) & $CRLF & _
        "Temp String 4 Length=" & STR$(LEN(File04(SequencePT))) & $CRLF & _
        "Temp String 5 Length=" & STR$(LEN(File05(SequencePT))) & $CRLF & _
        "Temp String 6 Length=" & STR$(LEN(File06(SequencePT))) & $CRLF & _
        "Temp String 7 Length=" & STR$(LEN(File07(SequencePT))) & $CRLF & _
        "Temp String 8 Length=" & STR$(LEN(File08(SequencePT))) & $CRLF & _
        "Temp String 9 Length=" & STR$(LEN(File09(SequencePT))) & $CRLF & _
        "Temp String 10 Length=" & STR$(LEN(File10(SequencePT)))& $CRLF & $CRLF & _
        "10 files were loaded."& $CRLF & _
        "The next group starts at " & STR$(NextPT) & $CRLF & _
        "Data Arrays Sequence Number=" & STR$(SequencePT)
    END SUB
    
    FUNCTION Legend() AS STRING : FUNCTION = STR$(ThreadsCount) + "x" + FORMAT$(URLsPerThread,"###0") : END FUNCTION
    
    SUB LoadURLs
      LOCAL i AS LONG
      REDIM URLs(1 TO FileTotal)
    
      URLs(1) = DIR$("threads\*.htm")
      FOR i = 2 TO UBOUND(URLs) : URLs(i) = DIR$(NEXT) : NEXT i
    END SUB
    
    SUB Load10Files
      LOCAL i01 AS LONG
      LOCAL i02 AS LONG
      LOCAL i03 AS LONG
      LOCAL i04 AS LONG
      LOCAL i05 AS LONG
      LOCAL i06 AS LONG
      LOCAL i07 AS LONG
      LOCAL i08 AS LONG
      LOCAL i09 AS LONG
      LOCAL i10 AS LONG
    
      INCR SequencePT
      'just open, read, and close 10 files
      i01 = FREEFILE
      OPEN "threads\" + URLs(StartPT + 0) FOR BINARY AS #i01 : GET$ #i01, LOF(#i01), File01(SequencePT) : CLOSE #i01
    
      i02 = FREEFILE
      OPEN "threads\" + URLs(StartPT + 1) FOR BINARY AS #i02 : GET$ #i02, LOF(i02), File02(SequencePT) : CLOSE #i02
    
      i03 = FREEFILE
      OPEN "threads\" + URLs(StartPT + 2) FOR BINARY AS #i03 : GET$ #i03, LOF(i03), File03(SequencePT) : CLOSE #i03
    
      i04 = FREEFILE
      OPEN "threads\" + URLs(StartPT + 3) FOR BINARY AS #i04 : GET$ #i04, LOF(i04), File04(SequencePT) : CLOSE #i04
    
      i05 = FREEFILE
      OPEN "threads\" + URLs(StartPT + 4) FOR BINARY AS #i05 : GET$ #i05, LOF(i05), File05(SequencePT) : CLOSE #i05
    
      i06 = FREEFILE
      OPEN "threads\" + URLs(StartPT + 5) FOR BINARY AS #i06 : GET$ #i06, LOF(i06), File06(SequencePT) : CLOSE #i06
    
      i07 = FREEFILE
      OPEN "threads\" + URLs(StartPT + 6) FOR BINARY AS #i07 : GET$ #i07, LOF(i07), File07(SequencePT) : CLOSE #i07
    
      i08 = FREEFILE
      OPEN "threads\" + URLs(StartPT + 7) FOR BINARY AS #i08 : GET$ #i08, LOF(i08), File08(SequencePT) : CLOSE #i08
    
      i09 = FREEFILE
      OPEN "threads\" + URLs(StartPT + 8) FOR BINARY AS #i09 : GET$ #i09, LOF(i09), File09(SequencePT) : CLOSE #i09
    
      i10 = FREEFILE
      OPEN "threads\" + URLs(StartPT + 9) FOR BINARY AS #i10 : GET$ #i10, LOF(i10), File10(SequencePT) : CLOSE #i10
      NextPT = StartPT + 10
    
    END SUB
    
    SUB Settings_INI(Task$)
       LOCAL xResult, yResult, tempZ, INIFileName AS WSTRINGZ * %MAX_PATH, WinPla AS WindowPlacement
       'set ini filename
       INIFileName = EXE.PATH$ + "threads.ini"
    
       IF Task$ = "get" THEN
    
          'get dialog width/height from INI file and use to set Dialog size
          GetPrivateProfileString "All", "Width", "1070", xResult, %MAX_PATH, INIFileName
          GetPrivateProfileString "All", "Height", "125", yResult, %MAX_PATH, INIFileName
          DIALOG SET SIZE hDlg,VAL(xResult), VAL(yResult)   'width/height
    
          'default position should be centered on screen
          LOCAL DefaultX, DefaultY, wDeskTop, hDeskTop AS LONG
          DESKTOP GET CLIENT TO wDeskTop, hDeskTop
          DefaultX = (wDeskTop-VAL(xResult))/2
          DefaultY = (hDeskTop-VAL(yResult))/2
    
          'get dialog top/left from INI file and use to set Dialog location
          Getprivateprofilestring "All", "Left", STR$(DefaultX), xResult, %MAX_PATH, INIFileName
          Getprivateprofilestring "All", "Top", STR$(DefaultY), yResult, %MAX_PATH, INIFileName
          DIALOG SET LOC hDlg, VAL(xResult), VAL(yResult)   'left/top
    
       END IF
    
       IF Task$ = "save" THEN
          'If Len(Dir$(INIFileName)) Then Kill INIFileName
          'save dialog size/location unless minimized or maximized
          WinPla.length = SIZEOF(WinPla)
          GetWindowPlacement hDlg, WinPla
          WritePrivateProfileString "All", "Left", STR$(WinPla.rcNormalPosition.nLeft), INIFileName
          WritePrivateProfileString "All", "Top", STR$(WinPla.rcNormalPosition.nTop), INIFileName
          WritePrivateProfileString "All", "Width", STR$(WinPla.rcNormalPosition.nRight - WinPla.rcNormalPosition.nLeft), INIFileName
          WritePrivateProfileString "All", "Height", STR$(WinPla.rcNormalPosition.nBottom - WinPla.rcNormalPosition.nTop), INIFileName
          WritePrivateProfileString "All", "MinMaxState", STR$(WinPla.showCmd), INIFileName
    
       END IF
    END SUB
    
    SUB ProcessFiles
      LOCAL i AS LONG
    
      StopAction = 0
      StartTime = TIME$
      QueryPerformanceCounter   qStart
      DIALOG SET TEXT hDlg, "Processing Threads ...      " + _
                  FORMAT$(UBOUND(URLS), "##,##0") + "    " + _
                  Legend + "   " + StartTime
    
      IF giThread01 = 0 OR _
         giThread02 = 0 OR _
         giThread03 = 0 OR _
         giThread04 = 0 OR _
         giThread05 = 0 OR _
         giThread06 = 0 OR _
         giThread07 = 0 OR _
         giThread08 = 0 OR _
         giThread09 = 0 OR _
         giThread10 = 0 THEN
          CALL CreateTheThreads
      END IF
      CALL SendFireCommand
    END SUB
    
    SUB CreateTheThreads
    
      StopAction = 0
    
      IF giThread01 = 0 THEN
          THREAD CREATE FormatThreads01(999) TO hThread01   : THREAD CLOSE hThread01 TO hThread01
      END IF
      IF giThread02 = 0 THEN
          THREAD CREATE FormatThreads02(999) TO hThread02   : THREAD CLOSE hThread02 TO hThread02
      END IF
      IF giThread03 = 0 THEN
          THREAD CREATE FormatThreads03(999) TO hThread03   : THREAD CLOSE hThread03 TO hThread03
      END IF
      IF giThread04 = 0 THEN
          THREAD CREATE FormatThreads04(999) TO hThread04   : THREAD CLOSE hThread04 TO hThread04
      END IF
      IF giThread05 = 0 THEN
          THREAD CREATE FormatThreads05(999) TO hThread05   : THREAD CLOSE hThread05 TO hThread05
      END IF
      IF giThread06 = 0 THEN
          THREAD CREATE FormatThreads06(999) TO hThread06   : THREAD CLOSE hThread06 TO hThread06
      END IF
      IF giThread07 = 0 THEN
          THREAD CREATE FormatThreads07(999) TO hThread07   : THREAD CLOSE hThread07 TO hThread07
      END IF
      IF giThread08 = 0 THEN
          THREAD CREATE FormatThreads08(999) TO hThread08   : THREAD CLOSE hThread08 TO hThread08
      END IF
      IF giThread09 = 0 THEN
          THREAD CREATE FormatThreads09(999) TO hThread09   : THREAD CLOSE hThread09 TO hThread09
      END IF
      IF giThread10 = 0 THEN
          THREAD CREATE FormatThreads10(999) TO hThread10   : THREAD CLOSE hThread10 TO hThread10
      END IF
      IF giThreadStore = 0 THEN
          THREAD CREATE StoreThreads(999) TO hThreadStore   : THREAD CLOSE hThreadStore TO hThreadStore
      END IF
    
      'wait for threads to start running
      SLEEP 20
    END SUB
    
    SUB SendFireCommand
      TryAgain:
      'Send Command to Fire up processing
      IF giAppRunning = 1 AND _
         giThread01 = 1   AND _
         giThread02 = 1   AND _
         giThread03 = 1   AND _
         giThread04 = 1   AND _
         giThread05 = 1   AND _
         giThread06 = 1   AND _
         giThread07 = 1   AND _
         giThread08 = 1   AND _
         giThread09 = 1   AND _
         giThread10 = 1   AND _
         PROCESSIT(1) = 0 AND _
         PROCESSIT(2) = 0 AND _
         PROCESSIT(3) = 0 AND _
         PROCESSIT(4) = 0 AND _
         PROCESSIT(5) = 0 AND _
         PROCESSIT(6) = 0 AND _
         PROCESSIT(7) = 0 AND _
         PROCESSIT(8) = 0 AND _
         PROCESSIT(9) = 0 AND _
         PROCESSIT(10) = 0 THEN
    
          CALL FireIt
      ELSE
          IF giAppRunning = 0 OR StopAction = 1 THEN EXIT SUB
          SLEEP 5
          GOTO TryAgain
      END IF
    END SUB
    
    SUB FireIt
      LOCAL Eo AS LONG
    
      FOR Eo = 1 TO 10
          'Fire command
          PROCESSIT(Eo) = 1
      NEXT
      '? "fire command sent"
    END SUB
    
    SUB ZeroThreadCompletion
      LOCAL Eo AS LONG
    
      FOR Eo = 1 TO 10
          'ResetFinished
          FINISHEDIT(Eo) = 0
      NEXT
      '? "Reset Finish"
    END SUB
    
    THREAD FUNCTION FormatThreads01(BYVAL x AS LONG) AS LONG
        LOCAL Io AS LONG
    
        giThread01 = 1
    
        WHILE giAppRunning = 1
            IF PROCESSIT(1) = 1 THEN
                INCR Io
                'do something to the content
                REPLACE "a" WITH "z" IN File01(Io)
                REPLACE "e" WITH "z" IN File01(Io)
                REPLACE "i" WITH "z" IN File01(Io)
                REPLACE "o" WITH "z" IN File01(Io)
                REPLACE "u" WITH "z" IN File01(Io)
                PROCESSIT(1) = 0
                FINISHEDIT(1) = 1
                IF FINISHEDIT(1) = 1 AND _
                   FINISHEDIT(2) = 1 AND _
                   FINISHEDIT(3) = 1 AND _
                   FINISHEDIT(4) = 1 AND _
                   FINISHEDIT(5) = 1 AND _
                   FINISHEDIT(6) = 1 AND _
                   FINISHEDIT(7) = 1 AND _
                   FINISHEDIT(8) = 1 AND _
                   FINISHEDIT(9) = 1 AND _
                   FINISHEDIT(10) = 1 THEN
                    CALL ZeroThreadCompletion
                    PostMessage hDlg, %WM_COMMAND, %IDC_Next, 0
                END IF
            END IF
            IF giAppRunning = 1 THEN SLEEP BreakTime
        WEND
        giThread01 = 0
    END FUNCTION
    
    THREAD FUNCTION FormatThreads02(BYVAL x AS LONG) AS LONG
        LOCAL Io AS LONG
    
        giThread02 = 1
    
        WHILE giAppRunning = 1
            IF PROCESSIT(2) = 1 THEN
                'FOR Io = StartPT + 251 TO StartPT + 500
                INCR Io
                'do something to the content
                REPLACE "a" WITH "z" IN File02(Io)
                REPLACE "e" WITH "z" IN File02(Io)
                REPLACE "i" WITH "z" IN File02(Io)
                REPLACE "o" WITH "z" IN File02(Io)
                REPLACE "u" WITH "z" IN File02(Io)
                PROCESSIT(2) = 0
                FINISHEDIT(2) = 1
                IF FINISHEDIT(1) = 1 AND _
                   FINISHEDIT(2) = 1 AND _
                   FINISHEDIT(3) = 1 AND _
                   FINISHEDIT(4) = 1 AND _
                   FINISHEDIT(5) = 1 AND _
                   FINISHEDIT(6) = 1 AND _
                   FINISHEDIT(7) = 1 AND _
                   FINISHEDIT(8) = 1 AND _
                   FINISHEDIT(9) = 1 AND _
                   FINISHEDIT(10) = 1 THEN
                    CALL ZeroThreadCompletion
                    PostMessage hDlg, %WM_COMMAND, %IDC_Next, 0
                END IF
            END IF
            IF giAppRunning = 1 THEN SLEEP BreakTime
        WEND
        giThread02 = 0
    END FUNCTION
    
    THREAD FUNCTION FormatThreads03(BYVAL x AS LONG) AS LONG
        LOCAL Io AS LONG
    
        giThread03 = 1
    
        WHILE giAppRunning = 1
            IF PROCESSIT(3) = 1 THEN
                'FOR Io = StartPT + 501 TO StartPT + 750
                'do something to the content
                INCR Io
                REPLACE "a" WITH "z" IN File03(Io)
                REPLACE "e" WITH "z" IN File03(Io)
                REPLACE "i" WITH "z" IN File03(Io)
                REPLACE "o" WITH "z" IN File03(Io)
                REPLACE "u" WITH "z" IN File03(Io)
                PROCESSIT(3) = 0
                FINISHEDIT(3) = 1
                IF FINISHEDIT(1) = 1 AND _
                   FINISHEDIT(2) = 1 AND _
                   FINISHEDIT(3) = 1 AND _
                   FINISHEDIT(4) = 1 AND _
                   FINISHEDIT(5) = 1 AND _
                   FINISHEDIT(6) = 1 AND _
                   FINISHEDIT(7) = 1 AND _
                   FINISHEDIT(8) = 1 AND _
                   FINISHEDIT(9) = 1 AND _
                   FINISHEDIT(10) = 1 THEN
                    CALL ZeroThreadCompletion
                    PostMessage hDlg, %WM_COMMAND, %IDC_Next, 0
                END IF
            END IF
            IF giAppRunning = 1 THEN SLEEP BreakTime
        WEND
        giThread03 = 0
    END FUNCTION
    
    THREAD FUNCTION FormatThreads04(BYVAL x AS LONG) AS LONG
        LOCAL Io AS LONG
    
        giThread04 = 1
    
        WHILE giAppRunning = 1
            IF PROCESSIT(4) = 1 THEN
                INCR Io
                'do something to the content
                REPLACE "a" WITH "z" IN File04(Io)
                REPLACE "e" WITH "z" IN File04(Io)
                REPLACE "i" WITH "z" IN File04(Io)
                REPLACE "o" WITH "z" IN File04(Io)
                REPLACE "u" WITH "z" IN File04(Io)
                PROCESSIT(4) = 0
                FINISHEDIT(4) = 1
                IF FINISHEDIT(1) = 1 AND _
                   FINISHEDIT(2) = 1 AND _
                   FINISHEDIT(3) = 1 AND _
                   FINISHEDIT(4) = 1 AND _
                   FINISHEDIT(5) = 1 AND _
                   FINISHEDIT(6) = 1 AND _
                   FINISHEDIT(7) = 1 AND _
                   FINISHEDIT(8) = 1 AND _
                   FINISHEDIT(9) = 1 AND _
                   FINISHEDIT(10) = 1 THEN
                    CALL ZeroThreadCompletion
                    PostMessage hDlg, %WM_COMMAND, %IDC_Next, 0
                END IF
            END IF
            IF giAppRunning = 1 THEN SLEEP BreakTime
        WEND
        giThread04 = 0
    END FUNCTION
    
    THREAD FUNCTION FormatThreads05(BYVAL x AS LONG) AS LONG
        LOCAL Io AS LONG
        giThread05 = 1
    
        WHILE giAppRunning = 1
            IF PROCESSIT(5) = 1 THEN
                INCR Io
                'do something to the content
                REPLACE "a" WITH "z" IN File05(Io)
                REPLACE "e" WITH "z" IN File05(Io)
                REPLACE "i" WITH "z" IN File05(Io)
                REPLACE "o" WITH "z" IN File05(Io)
                REPLACE "u" WITH "z" IN File05(Io)
                PROCESSIT(5) = 0
                FINISHEDIT(5) = 1
                IF FINISHEDIT(1) = 1 AND _
                   FINISHEDIT(2) = 1 AND _
                   FINISHEDIT(3) = 1 AND _
                   FINISHEDIT(4) = 1 AND _
                   FINISHEDIT(5) = 1 AND _
                   FINISHEDIT(6) = 1 AND _
                   FINISHEDIT(7) = 1 AND _
                   FINISHEDIT(8) = 1 AND _
                   FINISHEDIT(9) = 1 AND _
                   FINISHEDIT(10) = 1 THEN
                    CALL ZeroThreadCompletion
                    PostMessage hDlg, %WM_COMMAND, %IDC_Next, 0
                END IF
            END IF
            IF giAppRunning = 1 THEN SLEEP BreakTime
        WEND
        giThread05 = 0
    END FUNCTION
    
    THREAD FUNCTION FormatThreads06(BYVAL x AS LONG) AS LONG
        LOCAL Io AS LONG
    
        giThread06 = 1
    
        WHILE giAppRunning = 1
            IF PROCESSIT(6) = 1 THEN
                INCR Io
                'do something to the content
                REPLACE "a" WITH "z" IN File06(Io)
                REPLACE "e" WITH "z" IN File06(Io)
                REPLACE "i" WITH "z" IN File06(Io)
                REPLACE "o" WITH "z" IN File06(Io)
                REPLACE "u" WITH "z" IN File06(Io)
                PROCESSIT(6) = 0
                FINISHEDIT(6) = 1
                IF FINISHEDIT(1) = 1 AND _
                   FINISHEDIT(2) = 1 AND _
                   FINISHEDIT(3) = 1 AND _
                   FINISHEDIT(4) = 1 AND _
                   FINISHEDIT(5) = 1 AND _
                   FINISHEDIT(6) = 1 AND _
                   FINISHEDIT(7) = 1 AND _
                   FINISHEDIT(8) = 1 AND _
                   FINISHEDIT(9) = 1 AND _
                   FINISHEDIT(10) = 1 THEN
                    CALL ZeroThreadCompletion
                    PostMessage hDlg, %WM_COMMAND, %IDC_Next, 0
                END IF
            END IF
            IF giAppRunning = 1 THEN SLEEP BreakTime
        WEND
        giThread06 = 0
    END FUNCTION
    
    THREAD FUNCTION FormatThreads07(BYVAL x AS LONG) AS LONG
        LOCAL Io AS LONG
    
        giThread07 = 1
    
        WHILE giAppRunning = 1
            IF PROCESSIT(7) = 1 THEN
                INCR Io
                'do something to the content
                REPLACE "a" WITH "z" IN File07(Io)
                REPLACE "e" WITH "z" IN File07(Io)
                REPLACE "i" WITH "z" IN File07(Io)
                REPLACE "o" WITH "z" IN File07(Io)
                REPLACE "u" WITH "z" IN File07(Io)
                PROCESSIT(7) = 0
                FINISHEDIT(7) = 1
                IF FINISHEDIT(1) = 1 AND _
                   FINISHEDIT(2) = 1 AND _
                   FINISHEDIT(3) = 1 AND _
                   FINISHEDIT(4) = 1 AND _
                   FINISHEDIT(5) = 1 AND _
                   FINISHEDIT(6) = 1 AND _
                   FINISHEDIT(7) = 1 AND _
                   FINISHEDIT(8) = 1 AND _
                   FINISHEDIT(9) = 1 AND _
                   FINISHEDIT(10) = 1 THEN
                    CALL ZeroThreadCompletion
                    PostMessage hDlg, %WM_COMMAND, %IDC_Next, 0
                END IF
            END IF
            IF giAppRunning = 1 THEN SLEEP BreakTime
        WEND
        giThread07 = 0
    END FUNCTION
    
    THREAD FUNCTION FormatThreads08(BYVAL x AS LONG) AS LONG
        LOCAL Io AS LONG
    
        giThread08 = 1
    
        WHILE giAppRunning = 1
            IF PROCESSIT(8) = 1 THEN
                INCR Io
                'do something to the content
                REPLACE "a" WITH "z" IN File08(Io)
                REPLACE "e" WITH "z" IN File08(Io)
                REPLACE "i" WITH "z" IN File08(Io)
                REPLACE "o" WITH "z" IN File08(Io)
                REPLACE "u" WITH "z" IN File08(Io)
                PROCESSIT(8) = 0
                FINISHEDIT(8) = 1
                IF FINISHEDIT(1) = 1 AND _
                   FINISHEDIT(2) = 1 AND _
                   FINISHEDIT(3) = 1 AND _
                   FINISHEDIT(4) = 1 AND _
                   FINISHEDIT(5) = 1 AND _
                   FINISHEDIT(6) = 1 AND _
                   FINISHEDIT(7) = 1 AND _
                   FINISHEDIT(8) = 1 AND _
                   FINISHEDIT(9) = 1 AND _
                   FINISHEDIT(10) = 1 THEN
                    CALL ZeroThreadCompletion
                    PostMessage hDlg, %WM_COMMAND, %IDC_Next, 0
                END IF
            END IF
            IF giAppRunning = 1 THEN SLEEP BreakTime
        WEND
        giThread08 = 0
    END FUNCTION
    
    THREAD FUNCTION FormatThreads09(BYVAL x AS LONG) AS LONG
        LOCAL Io AS LONG
        giThread09 = 1
    
        WHILE giAppRunning = 1
            IF PROCESSIT(9) = 1 THEN
                INCR Io
                'do something to the content
                REPLACE "a" WITH "z" IN File09(Io)
                REPLACE "e" WITH "z" IN File09(Io)
                REPLACE "i" WITH "z" IN File09(Io)
                REPLACE "o" WITH "z" IN File09(Io)
                REPLACE "u" WITH "z" IN File09(Io)
                PROCESSIT(9) = 0
                FINISHEDIT(9) = 1
                IF FINISHEDIT(1) = 1 AND _
                   FINISHEDIT(2) = 1 AND _
                   FINISHEDIT(3) = 1 AND _
                   FINISHEDIT(4) = 1 AND _
                   FINISHEDIT(5) = 1 AND _
                   FINISHEDIT(6) = 1 AND _
                   FINISHEDIT(7) = 1 AND _
                   FINISHEDIT(8) = 1 AND _
                   FINISHEDIT(9) = 1 AND _
                   FINISHEDIT(10) = 1 THEN
                    CALL ZeroThreadCompletion
                    PostMessage hDlg, %WM_COMMAND, %IDC_Next, 0
                END IF
            END IF
            IF giAppRunning = 1 THEN SLEEP BreakTime
        WEND
        giThread09 = 0
    END FUNCTION
    
    THREAD FUNCTION FormatThreads10(BYVAL x AS LONG) AS LONG
        LOCAL Io AS LONG
        giThread10 = 1
    
        WHILE giAppRunning = 1
            IF PROCESSIT(10) = 1 THEN
                INCR Io
                'do something to the content
                REPLACE "a" WITH "z" IN File10(Io)
                REPLACE "e" WITH "z" IN File10(Io)
                REPLACE "i" WITH "z" IN File10(Io)
                REPLACE "o" WITH "z" IN File10(Io)
                REPLACE "u" WITH "z" IN File10(Io)
                PROCESSIT(10) = 0
                FINISHEDIT(10) = 1
                IF FINISHEDIT(1) = 1 AND _
                   FINISHEDIT(2) = 1 AND _
                   FINISHEDIT(3) = 1 AND _
                   FINISHEDIT(4) = 1 AND _
                   FINISHEDIT(5) = 1 AND _
                   FINISHEDIT(6) = 1 AND _
                   FINISHEDIT(7) = 1 AND _
                   FINISHEDIT(8) = 1 AND _
                   FINISHEDIT(9) = 1 AND _
                   FINISHEDIT(10) = 1 THEN
                    CALL ZeroThreadCompletion
                    PostMessage hDlg, %WM_COMMAND, %IDC_Next, 0
                END IF
            END IF
            IF giAppRunning = 1 THEN SLEEP BreakTime
        WEND
        giThread10 = 0
    END FUNCTION
    
    THREAD FUNCTION StoreThreads(BYVAL x AS LONG) AS LONG
        LOCAL Io  AS LONG
        LOCAL i01 AS LONG
        LOCAL i02 AS LONG
        LOCAL i03 AS LONG
        LOCAL i04 AS LONG
        LOCAL i05 AS LONG
        LOCAL i06 AS LONG
        LOCAL i07 AS LONG
        LOCAL i08 AS LONG
        LOCAL i09 AS LONG
        LOCAL i10 AS LONG
        LOCAL Seq AS LONG
    
        giThreadStore = 1
    
        WHILE giAppRunning = 1
            IF StoreIt = 1 AND StopAction = 0 THEN
                StoreIt = 0
                'remove formatted files on first run
                IF DIR$(EXE.PATH$ & "threads_formatted\*.HTM") <> "" AND giWipedFolder = 0 THEN
                    KILL EXE.PATH$ & "threads_formatted\*.HTM"
                    giWipedFolder = 1
                END IF
                'save results
                FOR Io = 1 TO UBOUND(File01())
                    INCR Seq
                    i01 = FREEFILE
                    OPEN "threads_formatted\" + URLs(Seq) FOR OUTPUT AS #i01 : PRINT #i01, File01(Io); : CLOSE #i01
                    File01(Io) = ""
    
                    INCR Seq
                    i02 = FREEFILE
                    OPEN "threads_formatted\" + URLs(Seq) FOR OUTPUT AS #i02 : PRINT #i02, File02(Io); : CLOSE #i02
                    File02(Io) = ""
    
                    INCR Seq
                    i03 = FREEFILE
                    OPEN "threads_formatted\" + URLs(Seq) FOR OUTPUT AS #i03 : PRINT #i03, File03(Io); : CLOSE #i03
                    File03(Io) = ""
    
                    INCR Seq
                    i04 = FREEFILE
                    OPEN "threads_formatted\" + URLs(Seq) FOR OUTPUT AS #i04 : PRINT #i04, File04(Io); : CLOSE #i04
                    File04(Io) = ""
    
                    INCR Seq
                    i05 = FREEFILE
                    OPEN "threads_formatted\" + URLs(Seq) FOR OUTPUT AS #i05 : PRINT #i05, File05(Io); : CLOSE #i05
                    File05(Io) = ""
    
                    INCR Seq
                    i06 = FREEFILE
                    OPEN "threads_formatted\" + URLs(Seq) FOR OUTPUT AS #i06 : PRINT #i06, File06(Io); : CLOSE #i06
                    File06(Io) = ""
    
                    INCR Seq
                    i07 = FREEFILE
                    OPEN "threads_formatted\" + URLs(Seq) FOR OUTPUT AS #i07 : PRINT #i07, File07(Io); : CLOSE #i07
                    File07(Io) = ""
    
                    INCR Seq
                    i08 = FREEFILE
                    OPEN "threads_formatted\" + URLs(Seq) FOR OUTPUT AS #i08 : PRINT #i08, File08(Io); : CLOSE #i08
                    File08(Io) = ""
    
                    INCR Seq
                    i09 = FREEFILE
                    OPEN "threads_formatted\" + URLs(Seq) FOR OUTPUT AS #i09 : PRINT #i09, File09(Io); : CLOSE #i09
                    File09(Io) = ""
    
                    INCR Seq
                    i10 = FREEFILE
                    OPEN "threads_formatted\" + URLs(Seq) FOR OUTPUT AS #i10 : PRINT #i10, File10(Io); : CLOSE #i10
                    File10(Io) = ""
    
                NEXT Io
                Seq = 0  'last update
                PostMessage hDlg, %WM_COMMAND, %IDC_Finished, 0
            END IF
    
            IF giAppRunning = 1 THEN SLEEP BreakTime
        WEND
    
        giThreadStore = 0
    END FUNCTION
    Last edited by Jim Fritts; 21 Aug 2020, 08:44 AM.

    #2
    Version 4
    1 internal thread that processes the files. The number of processes is selectable. 1, 2, 4, 5, 10, 20.
    It appears that process time and save time are the biggest contributors to the overall speed of the application.
    As the number of processes are reduced the delta time increases significantly . The thread BreakTime is set to 1.

    Click image for larger version  Name:	New Bitmap Image.jpg Views:	0 Size:	37.6 KB ID:	798590

    Code:
    'Compilable Example:
    #COMPILE EXE "threadsV4.exe"
    #DIM ALL
    
    'Updated by Jim Fritts on 2020-AUG-23
    'Designed to run on Windows 10 2004
    'Platform: PBWIN10 and J. Roca includes
    'To use this program as is you will need to download Gary Beene's sample files from
    'http://www.garybeene.com/files/threads.zip
    'Replace his Threads.bas with this app.
    'As a comparison Gary's unmodified code ran 6.1 minutes for 2000 files.
    'My modified version uses 11 threads and ran 12.4 seconds for 2000 files.
    
    'Comments here please:
    'https://forum.powerbasic.com/forum/user-to-user-discussions/programming/798049-effect-of-multiple-threads?p=798321#post798321
    
    'NOTE: the first time through after the app is launched the results are longer.
    ' I created 2000 duplicate files so the app could be tested on 4000 files.
    
    ' Files Processed 4,000
    ' Processes       20
    ' Read Time       2.046
    ' Process Time   21.76
    ' Save Time      10.798
    ' Component Time 34.604
    ' Overall Time   34.972
    ' Delta Time      0.368 < smallest
    ' Time per file   0.009
    
    ' Files Processed 4,000
    ' Processes       10
    ' Read Time       2.011
    ' Process Time   21.492
    ' Save Time      10.556
    ' Component Time 34.059
    ' Overall Time   34.822
    ' Delta Time      0.763 < higher
    ' Time per file   0.009
    
    ' Files Processed 4,000
    ' Processes       5
    ' Read Time       2.079
    ' Process Time   22.608
    ' Save Time      10.066
    ' Component Time 34.752
    ' Overall Time   36.401
    ' Delta Time      1.649 < higher
    ' Time per file   0.009
    
    ' Files Processed 4,000
    ' Processes       4
    ' Read Time       2.023
    ' Process Time   21.416
    ' Save Time      11.788
    ' Component Time 35.227
    ' Overall Time   37.14
    ' Delta Time      1.913 < higher
    ' Time per file   0.009
    
    ' Files Processed 4,000
    ' Processes       2
    ' Read Time       2.192
    ' Process Time   23.274
    ' Save Time      10.596
    ' Component Time 36.062
    ' Overall Time   40.512
    ' Delta Time      4.449 < higher
    ' Time per file   0.01
    
    ' Files Processed 4,000
    ' Processes       1
    ' Read Time       2.408
    ' Process Time   22.868
    ' Save Time      10.89
    ' Component Time 36.166
    ' Overall Time   45.112
    ' Delta Time      8.946 < highest
    ' Time per file   0.011
    
    
    #DEBUG ERROR ON
    #DEBUG DISPLAY ON
    
    %Unicode = 1
    #INCLUDE "Win32API.inc"
    
    #RESOURCE ICON logo, "index.ico"
    
    ENUM Equates SINGULAR
       IDC_Stop = 1500
       IDC_Start
       IDC_Next
       IDC_Finished
       IDC_SaveAndLoad
       IDC_Label_01
       IDC_ProcessOne
       IDC_ProcessTwo
       IDC_ProcessFour
       IDC_ProcessFive
       IDC_ProcessTen
       IDC_ProcessTwenty
       IDC_Label_02
       IDC_Text_01
    
    END ENUM
    
    GLOBAL hDlg          AS LONG
    GLOBAL StopAction    AS LONG
    GLOBAL URLsPerThread AS LONG
    GLOBAL ThreadsCount  AS LONG
    GLOBAL hThread01, _
           hThread02, _
           hThread03, _
           hThread04, _
           hThread05, _
           hThread06, _
           hThread07, _
           hThread08, _
           hThread09, _
           hThread10, _
           hThreadStore  AS DWORD
    GLOBAL URLS()        AS STRING    'file name array shared between main app and storage thread
    GLOBAL StartTime     AS STRING
    
    GLOBAL qFreq         AS QUAD
    GLOBAL qStart        AS QUAD
    GLOBAL qStop         AS QUAD
    
    GLOBAL qStartRead    AS QUAD
    GLOBAL qStopRead     AS QUAD
    GLOBAL qReadAccum    AS QUAD
    
    GLOBAL qStartProcess AS QUAD
    GLOBAL qStopProcess  AS QUAD
    GLOBAL qProcessAccum AS QUAD
    
    GLOBAL qStartSave    AS QUAD
    GLOBAL qStopSave     AS QUAD
    GLOBAL qSaveAccum    AS QUAD
    
    GLOBAL StartPT       AS LONG  'jumps by ProcessCnt each time
    GLOBAL NextPT        AS LONG
    GLOBAL ProcessCnt    AS LONG
    GLOBAL FireIt        AS LONG
    
    GLOBAL giWipedFolder AS LONG
    GLOBAL StoreIt       AS LONG
    
    GLOBAL giThread01    AS LONG
    
    GLOBAL File01        AS STRING
    GLOBAL File02        AS STRING
    GLOBAL File03        AS STRING
    GLOBAL File04        AS STRING
    GLOBAL File05        AS STRING
    GLOBAL File06        AS STRING
    GLOBAL File07        AS STRING
    GLOBAL File08        AS STRING
    GLOBAL File09        AS STRING
    GLOBAL File10        AS STRING
    
    GLOBAL File11        AS STRING
    GLOBAL File12        AS STRING
    GLOBAL File13        AS STRING
    GLOBAL File14        AS STRING
    GLOBAL File15        AS STRING
    GLOBAL File16        AS STRING
    GLOBAL File17        AS STRING
    GLOBAL File18        AS STRING
    GLOBAL File19        AS STRING
    GLOBAL File20        AS STRING
    
    GLOBAL giAppRunning AS LONG
    GLOBAL FileTotal    AS LONG
    GLOBAL BreakTime    AS LONG
    
    FUNCTION PBMAIN() AS LONG
       LOCAL i    AS LONG
       LOCAL Time AS TIMECAPS
    
       TimeGetDevCaps ( Time, SIZEOF(Time) )
       timeBeginPeriod (Time.wPeriodMin)
       SLEEP 16
    
       FileTotal = 4000
       ProcessCnt = 20
       BreakTime = 1 '10
    
       DIALOG DEFAULT FONT "Tahoma",12, 0
       DIALOG NEW PIXELS, 0, "Process Files",,,260,305, %WS_OVERLAPPEDWINDOW TO hDlg
       DIALOG SET ICON hDlg, "logo"
       CONTROL ADD BUTTON, hDlg, %IDC_Start,"Start", 10,10,70,25
       CONTROL ADD BUTTON, hDlg, %IDC_Stop,"Stop", 90,10,70,25
       CONTROL DISABLE hDlg, %IDC_Stop
    
       'Processes per thread
       CONTROL ADD LABEL, hDlg, %IDC_Label_01, "Select processes per thread", 10,40,235,25, %SS_CENTER
       CONTROL ADD CHECKBOX, hDlg, %IDC_ProcessOne   , "1", 10,65,40,25, %WS_GROUP OR %WS_TABSTOP OR %BS_PUSHLIKE
       CONTROL ADD CHECKBOX, hDlg, %IDC_ProcessTwo   , "2", 50,65,40,25, %WS_TABSTOP OR %BS_PUSHLIKE
       CONTROL ADD CHECKBOX, hDlg, %IDC_ProcessFour  , "4", 90,65,40,25, %WS_TABSTOP OR %BS_PUSHLIKE
       CONTROL ADD CHECKBOX, hDlg, %IDC_ProcessFive  , "5",130,65,40,25, %WS_TABSTOP OR %BS_PUSHLIKE
       CONTROL ADD CHECKBOX, hDlg, %IDC_ProcessTen   ,"10",170,65,40,25, %WS_TABSTOP OR %BS_PUSHLIKE
       CONTROL ADD CHECKBOX, hDlg, %IDC_ProcessTwenty,"20",210,65,40,25, %WS_TABSTOP OR %BS_PUSHLIKE
       CONTROL ADD LABEL, hDlg, %IDC_Label_02, "Results: Times in seconds", 10,90,235,25, %SS_CENTER
       CONTROL ADD TEXTBOX, hDlg, %IDC_Text_01, "", 10,115,240,180, %ES_MULTILINE OR %ES_AUTOHSCROLL OR %ES_AUTOVSCROLL
    
       SELECT CASE ProcessCnt
           CASE 1,2,4,5,10,20
               IF ProcessCnt = 20 THEN
                   CONTROL SET CHECK hDlg, %IDC_ProcessTwenty, 1
               END IF
               IF ProcessCnt = 10 THEN
                   CONTROL SET CHECK hDlg, %IDC_ProcessTen, 1
               END IF
               IF ProcessCnt = 5 THEN
                   CONTROL SET CHECK hDlg, %IDC_ProcessFive, 1
               END IF
               IF ProcessCnt = 4 THEN
                   CONTROL SET CHECK hDlg, %IDC_ProcessFour, 1
               END IF
               IF ProcessCnt = 2 THEN
                   CONTROL SET CHECK hDlg, %IDC_ProcessTwo, 1
               END IF
               IF ProcessCnt = 1 THEN
                   CONTROL SET CHECK hDlg, %IDC_ProcessOne, 1
               END IF
    
           CASE ELSE
               ? "The process count is not set correctly!" & $CRLF & _
                 "ProcessCnt should be 1, 2, 4, 5, 10, or 20." & $CRLF & $CRLF & _
                 "This program will close."
               EXIT FUNCTION
       END SELECT
    
       DIALOG SHOW MODAL hDlg CALL DlgProc
    END FUNCTION
    
    CALLBACK FUNCTION DlgProc() AS LONG
       SELECT CASE CB.MSG
          CASE %WM_INITDIALOG
              IF ISFALSE ISFOLDER("threads_formatted") THEN MKDIR "threads_formatted"
              'Settings_INI "get"
              CALL LoadURLs      '1 to FileTotal
              QueryPerformanceFrequency qFreq
              giAppRunning = 1
              StartPT = 1
              'remove formatted files on first run
              IF DIR$(EXE.PATH$ & "threads_formatted\*.HTM") <> "" AND giWipedFolder = 0 THEN
                  KILL EXE.PATH$ & "threads_formatted\*.HTM"
                  giWipedFolder = 1
              END IF
              CALL CreateTheThreads
    
          CASE %WM_DESTROY
              winbeep(3000, 75)
              giAppRunning = 0
              Settings_INI "save"
    
          CASE %WM_COMMAND
              SELECT CASE CB.CTL
                  CASE %IDC_ProcessOne
                      CONTROL SET TEXT hDlg, %IDC_Text_01, ""
                      CONTROL SET CHECK hDlg, %IDC_ProcessTwenty, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessTen, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessFive, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessFour, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessTwo, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessOne, 1
                      ProcessCnt = 1
    
                  CASE %IDC_ProcessTwo
                      CONTROL SET TEXT hDlg, %IDC_Text_01, ""
                      CONTROL SET CHECK hDlg, %IDC_ProcessTwenty, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessTen, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessFive, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessFour, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessOne, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessTwo, 1
                      ProcessCnt = 2
    
                  CASE %IDC_ProcessFour
                      CONTROL SET TEXT hDlg, %IDC_Text_01, ""
                      CONTROL SET CHECK hDlg, %IDC_ProcessTwenty, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessTen, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessFive, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessOne, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessTwo, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessFour, 1
                      ProcessCnt = 4
    
                  CASE %IDC_ProcessFive
                      CONTROL SET TEXT hDlg, %IDC_Text_01, ""
                      CONTROL SET CHECK hDlg, %IDC_ProcessTwenty, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessTen, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessFour, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessOne, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessTwo, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessFive, 1
                      ProcessCnt = 5
    
                  CASE %IDC_ProcessTen
                      CONTROL SET TEXT hDlg, %IDC_Text_01, ""
                      CONTROL SET CHECK hDlg, %IDC_ProcessTwenty, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessFive, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessFour, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessOne, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessTwo, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessTen, 1
                      ProcessCnt = 10
    
                  CASE %IDC_ProcessTwenty
                      CONTROL SET TEXT hDlg, %IDC_Text_01, ""
                      CONTROL SET CHECK hDlg, %IDC_ProcessTen, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessFive, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessFour, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessOne, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessTwo, 0
                      CONTROL SET CHECK hDlg, %IDC_ProcessTwenty, 1
                      ProcessCnt = 20
    
                  CASE %IDC_Stop     : StopAction = 1
                      CONTROL ENABLE hDlg, %IDC_Start
                      CONTROL DISABLE hDlg, %IDC_Stop
                      DIALOG SET TEXT hDlg, "Process Files"
    
                  CASE %IDC_Start    : ThreadsCount = ProcessCnt  : URLsPerThread = 1  : ProcessFiles
                  CASE %IDC_SaveAndLoad
                      CALL SaveAndLoad
    
                  CASE %IDC_Finished
                      'there will be a small time delay here
                      QueryPerformanceCounter   qStop
                      DIALOG SET TEXT hDlg, "Completed"
    
                      CONTROL ENABLE hDlg, %IDC_Start
                      CONTROL DISABLE hDlg, %IDC_Stop
                      CONTROL ENABLE hDlg, %IDC_ProcessOne
                      CONTROL ENABLE hDlg, %IDC_ProcessTwo
                      CONTROL ENABLE hDlg, %IDC_ProcessFour
                      CONTROL ENABLE hDlg, %IDC_ProcessFive
                      CONTROL ENABLE hDlg, %IDC_ProcessTen
                      CONTROL ENABLE hDlg, %IDC_ProcessTwenty
                      CONTROL SET TEXT hDlg, %IDC_Text_01, _
                            " Files Processed " & $TAB & FORMAT$(UBOUND(URLS), "##,##0") & $CRLF & _
                            " Processes" & $TAB & LTRIM$(STR$(ProcessCnt)) & $CRLF & _
                            " Read Time " & $TAB + FORMAT$(qReadAccum/qFreq,"###.###") & $CRLF & _
                            " Process Time " & $TAB + FORMAT$(qProcessAccum/qFreq,"###.###") & $CRLF & _
                            " Save Time " & $TAB + FORMAT$(qSaveAccum/qFreq,"###.###") & $CRLF & _
                            " Component Time " & $TAB + FORMAT$((qReadAccum + qProcessAccum + qSaveAccum)/qFreq,"###.###") & $CRLF & _
                            " Overall Time " & $TAB + FORMAT$((qStop-qStart)/qFreq,"###.###") & $CRLF & _
                            " Delta Time " & $TAB + FORMAT$((qStop-qStart - (qReadAccum + qProcessAccum + qSaveAccum))/qFreq,"###.###") & $CRLF & _
                            " Time per file " & $TAB + FORMAT$(((qStop-qStart)/UBOUND(URLS))/qFreq,"###.#####")
    
              END SELECT
       END SELECT
    END FUNCTION
    
    SUB LoadURLs
      LOCAL i AS LONG
      REDIM URLs(1 TO FileTotal)
    
      URLs(1) = DIR$("threads\*.htm")
      FOR i = 2 TO UBOUND(URLs) : URLs(i) = DIR$(NEXT) : NEXT i
    END SUB
    
    
    SUB Settings_INI(Task$)
       LOCAL xResult, yResult, tempZ, INIFileName AS WSTRINGZ * %MAX_PATH, WinPla AS WindowPlacement
       'set ini filename
       INIFileName = EXE.PATH$ + "threads.ini"
    
       IF Task$ = "get" THEN
    
          'get dialog width/height from INI file and use to set Dialog size
          GetPrivateProfileString "All", "Width", "1070", xResult, %MAX_PATH, INIFileName
          GetPrivateProfileString "All", "Height", "125", yResult, %MAX_PATH, INIFileName
          DIALOG SET SIZE hDlg,VAL(xResult), VAL(yResult)   'width/height
    
          'default position should be centered on screen
          LOCAL DefaultX, DefaultY, wDeskTop, hDeskTop AS LONG
          DESKTOP GET CLIENT TO wDeskTop, hDeskTop
          DefaultX = (wDeskTop-VAL(xResult))/2
          DefaultY = (hDeskTop-VAL(yResult))/2
    
          'get dialog top/left from INI file and use to set Dialog location
          Getprivateprofilestring "All", "Left", STR$(DefaultX), xResult, %MAX_PATH, INIFileName
          Getprivateprofilestring "All", "Top", STR$(DefaultY), yResult, %MAX_PATH, INIFileName
          DIALOG SET LOC hDlg, VAL(xResult), VAL(yResult)   'left/top
    
       END IF
    
       IF Task$ = "save" THEN
          'If Len(Dir$(INIFileName)) Then Kill INIFileName
          'save dialog size/location unless minimized or maximized
          WinPla.length = SIZEOF(WinPla)
          GetWindowPlacement hDlg, WinPla
          WritePrivateProfileString "All", "Left", STR$(WinPla.rcNormalPosition.nLeft), INIFileName
          WritePrivateProfileString "All", "Top", STR$(WinPla.rcNormalPosition.nTop), INIFileName
          WritePrivateProfileString "All", "Width", STR$(WinPla.rcNormalPosition.nRight - WinPla.rcNormalPosition.nLeft), INIFileName
          WritePrivateProfileString "All", "Height", STR$(WinPla.rcNormalPosition.nBottom - WinPla.rcNormalPosition.nTop), INIFileName
          WritePrivateProfileString "All", "MinMaxState", STR$(WinPla.showCmd), INIFileName
    
       END IF
    END SUB
    
    SUB ProcessFiles
      LOCAL i AS LONG
    
      qReadAccum = 0
      qProcessAccum = 0
      qSaveAccum = 0
    
      StopAction = 0
      StartPT = 1
      NextPT = 1
      StartTime = TIME$
      QueryPerformanceCounter   qStart
      DIALOG SET TEXT hDlg, "Processing..."
    
      CONTROL SET TEXT hDlg, %IDC_Text_01, ""
      CONTROL DISABLE hDlg, %IDC_Start
      CONTROL ENABLE hDlg, %IDC_Stop
    
      CONTROL DISABLE hDlg, %IDC_ProcessOne
      CONTROL DISABLE hDlg, %IDC_ProcessTwo
      CONTROL DISABLE hDlg, %IDC_ProcessFour
      CONTROL DISABLE hDlg, %IDC_ProcessFive
      CONTROL DISABLE hDlg, %IDC_ProcessTen
      CONTROL DISABLE hDlg, %IDC_ProcessTwenty
    
      CALL LoadFiles
    END SUB
    
    
    SUB CreateTheThreads
    
      StopAction = 0
      IF giThread01 = 0 THEN
          THREAD CREATE FT01(999) TO hThread01   : THREAD CLOSE hThread01 TO hThread01
      END IF
    
      'wait for threads to start running
      SLEEP 20
    END SUB
    
    
    SUB SaveAndLoad
      IF StartPt > UBOUND(URLS()) THEN
          PostMessage hDlg, %WM_COMMAND, %IDC_Finished, 0
          EXIT SUB
      END IF
      CALL SaveFiles
    
      StartPT = NextPT
    
      IF NextPt > UBOUND(URLS()) THEN
          PostMessage hDlg, %WM_COMMAND, %IDC_Finished, 0
          EXIT SUB
      END IF
      CALL LoadFiles
    END SUB
    
    'Thread based sequential processing method
    THREAD FUNCTION FT01(BYVAL x AS LONG) AS LONG
        LOCAL GoNext AS LONG
    
        giThread01 = 1
    
        WHILE giAppRunning = 1
            IF FireIt = 1 THEN
                QueryPerformanceCounter qStartProcess
                FireIt = 0
                GoNext = 1
                IF StopAction = 0 AND giAppRunning = 1 THEN
                    IF GoNext = 1 THEN
                        GoNext = 0
                        'do something to the content
                        REPLACE "a" WITH "z" IN File01
                        REPLACE "e" WITH "z" IN File01
                        REPLACE "i" WITH "z" IN File01
                        REPLACE "o" WITH "z" IN File01
                        REPLACE "u" WITH "z" IN File01
                        IF ProcessCnt = 1 THEN
                            QueryPerformanceCounter qStopProcess
                            qProcessAccum = qProcessAccum + (qStopProcess - qStartProcess)
                            PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                            GOTO Leave
                        ELSE
                            GoNext = 1
                        END IF
                    END IF
    
                    IF GoNext = 1 THEN
                        GoNext = 0
                        'do something to the content
                        REPLACE "a" WITH "z" IN File02
                        REPLACE "e" WITH "z" IN File02
                        REPLACE "i" WITH "z" IN File02
                        REPLACE "o" WITH "z" IN File02
                        REPLACE "u" WITH "z" IN File02
                        IF ProcessCnt = 2 THEN
                            QueryPerformanceCounter qStopProcess
                            qProcessAccum = qProcessAccum + (qStopProcess - qStartProcess)
                            PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                            GOTO Leave
                        ELSE
                            GoNext = 1
                        END IF
                    END IF
    
                    IF GoNext = 1 THEN
                        GoNext = 0
                        'do something to the content
                        REPLACE "a" WITH "z" IN File03
                        REPLACE "e" WITH "z" IN File03
                        REPLACE "i" WITH "z" IN File03
                        REPLACE "o" WITH "z" IN File03
                        REPLACE "u" WITH "z" IN File03
                        'IF ProcessCnt = 3 THEN
                        '    PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                        '    EXIT IF
                        'ELSE
                            GoNext = 1
                        'END IF
                    END IF
    
                    IF GoNext = 1 THEN
                        GoNext = 0
                        'do something to the content
                        REPLACE "a" WITH "z" IN File04
                        REPLACE "e" WITH "z" IN File04
                        REPLACE "i" WITH "z" IN File04
                        REPLACE "o" WITH "z" IN File04
                        REPLACE "u" WITH "z" IN File04
                        IF ProcessCnt = 4 THEN
                            QueryPerformanceCounter qStopProcess
                            qProcessAccum = qProcessAccum + (qStopProcess - qStartProcess)
                            PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                            GOTO Leave
                        ELSE
                            GoNext = 1
                        END IF
                    END IF
    
                    IF GoNext = 1 THEN
                        GoNext = 0
                        'do something to the content
                        REPLACE "a" WITH "z" IN File05
                        REPLACE "e" WITH "z" IN File05
                        REPLACE "i" WITH "z" IN File05
                        REPLACE "o" WITH "z" IN File05
                        REPLACE "u" WITH "z" IN File05
                        IF ProcessCnt = 5 THEN
                            QueryPerformanceCounter qStopProcess
                            qProcessAccum = qProcessAccum + (qStopProcess - qStartProcess)
                            PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                            GOTO Leave
                        ELSE
                            GoNext = 1
                        END IF
                    END IF
    
                    IF GoNext = 1 THEN
                        GoNext = 0
                        'do something to the content
                        REPLACE "a" WITH "z" IN File06
                        REPLACE "e" WITH "z" IN File06
                        REPLACE "i" WITH "z" IN File06
                        REPLACE "o" WITH "z" IN File06
                        REPLACE "u" WITH "z" IN File06
                        'IF ProcessCnt = 6 THEN
                        '    PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                        '    EXIT IF
                        'ELSE
                            GoNext = 1
                        'END IF
                    END IF
    
                    IF GoNext = 1 THEN
                        GoNext = 0
                        'do something to the content
                        REPLACE "a" WITH "z" IN File07
                        REPLACE "e" WITH "z" IN File07
                        REPLACE "i" WITH "z" IN File07
                        REPLACE "o" WITH "z" IN File07
                        REPLACE "u" WITH "z" IN File07
                        'IF ProcessCnt = 7 THEN
                        '    PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                        '    EXIT IF
                        'ELSE
                            GoNext = 1
                        'END IF
                    END IF
    
                    IF GoNext = 1 THEN
                        GoNext = 0
                        'do something to the content
                        REPLACE "a" WITH "z" IN File08
                        REPLACE "e" WITH "z" IN File08
                        REPLACE "i" WITH "z" IN File08
                        REPLACE "o" WITH "z" IN File08
                        REPLACE "u" WITH "z" IN File08
                        'IF ProcessCnt = 8 THEN
                        '    PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                        '    EXIT IF
                        'ELSE
                            GoNext = 1
                        'END IF
                    END IF
    
                    IF GoNext = 1 THEN
                        GoNext = 0
                        'do something to the content
                        REPLACE "a" WITH "z" IN File09
                        REPLACE "e" WITH "z" IN File09
                        REPLACE "i" WITH "z" IN File09
                        REPLACE "o" WITH "z" IN File09
                        REPLACE "u" WITH "z" IN File09
                        'IF ProcessCnt = 9 THEN
                        '    PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                        '    EXIT IF
                        'ELSE
                            GoNext = 1
                        'END IF
                    END IF
    
                    IF GoNext = 1 THEN
                        GoNext = 0
                        'do something to the content
                        REPLACE "a" WITH "z" IN File10
                        REPLACE "e" WITH "z" IN File10
                        REPLACE "i" WITH "z" IN File10
                        REPLACE "o" WITH "z" IN File10
                        REPLACE "u" WITH "z" IN File10
                        IF ProcessCnt = 10 THEN
                            QueryPerformanceCounter qStopProcess
                            qProcessAccum = qProcessAccum + (qStopProcess - qStartProcess)
                            PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                            GOTO Leave
                        ELSE
                            GoNext = 1
                        END IF
                    END IF
    
                    IF GoNext = 1 THEN
                        GoNext = 0
                        'do something to the content
                        REPLACE "a" WITH "z" IN File11
                        REPLACE "e" WITH "z" IN File11
                        REPLACE "i" WITH "z" IN File11
                        REPLACE "o" WITH "z" IN File11
                        REPLACE "u" WITH "z" IN File11
                        'IF ProcessCnt = 11 THEN
                        '    PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                        '    EXIT IF
                        'ELSE
                            GoNext = 1
                        'END IF
                    END IF
    
                    IF GoNext = 1 THEN
                        GoNext = 0
                        'do something to the content
                        REPLACE "a" WITH "z" IN File12
                        REPLACE "e" WITH "z" IN File12
                        REPLACE "i" WITH "z" IN File12
                        REPLACE "o" WITH "z" IN File12
                        REPLACE "u" WITH "z" IN File12
                        'IF ProcessCnt = 12 THEN
                        '    PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                        '    EXIT IF
                        'ELSE
                            GoNext = 1
                        'END IF
                    END IF
    
                    IF GoNext = 1 THEN
                        GoNext = 0
                        'do something to the content
                        REPLACE "a" WITH "z" IN File13
                        REPLACE "e" WITH "z" IN File13
                        REPLACE "i" WITH "z" IN File13
                        REPLACE "o" WITH "z" IN File13
                        REPLACE "u" WITH "z" IN File13
                        'IF ProcessCnt = 13 THEN
                        '    PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                        '    EXIT IF
                        'ELSE
                            GoNext = 1
                        'END IF
                    END IF
    
                    IF GoNext = 1 THEN
                        GoNext = 0
                        'do something to the content
                        REPLACE "a" WITH "z" IN File14
                        REPLACE "e" WITH "z" IN File14
                        REPLACE "i" WITH "z" IN File14
                        REPLACE "o" WITH "z" IN File14
                        REPLACE "u" WITH "z" IN File14
                        'IF ProcessCnt = 14 THEN
                        '    PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                        '    EXIT IF
                        'ELSE
                            GoNext = 1
                        'END IF
                    END IF
    
                    IF GoNext = 1 THEN
                        GoNext = 0
                        'do something to the content
                        REPLACE "a" WITH "z" IN File15
                        REPLACE "e" WITH "z" IN File15
                        REPLACE "i" WITH "z" IN File15
                        REPLACE "o" WITH "z" IN File15
                        REPLACE "u" WITH "z" IN File15
                        'IF ProcessCnt = 15 THEN
                        '    PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                        '    EXIT IF
                        'ELSE
                            GoNext = 1
                        'END IF
                    END IF
    
                    IF GoNext = 1 THEN
                        GoNext = 0
                        'do something to the content
                        REPLACE "a" WITH "z" IN File16
                        REPLACE "e" WITH "z" IN File16
                        REPLACE "i" WITH "z" IN File16
                        REPLACE "o" WITH "z" IN File16
                        REPLACE "u" WITH "z" IN File16
                        'IF ProcessCnt = 16 THEN
                        '    PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                        '    EXIT IF
                        'ELSE
                            GoNext = 1
                        'END IF
                    END IF
    
                    IF GoNext = 1 THEN
                        GoNext = 0
                        'do something to the content
                        REPLACE "a" WITH "z" IN File17
                        REPLACE "e" WITH "z" IN File17
                        REPLACE "i" WITH "z" IN File17
                        REPLACE "o" WITH "z" IN File17
                        REPLACE "u" WITH "z" IN File17
                        'IF ProcessCnt = 17 THEN
                        '    PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                        '    EXIT IF
                        'ELSE
                            GoNext = 1
                        'END IF
                    END IF
    
                    IF GoNext = 1 THEN
                        GoNext = 0
                        'do something to the content
                        REPLACE "a" WITH "z" IN File18
                        REPLACE "e" WITH "z" IN File18
                        REPLACE "i" WITH "z" IN File18
                        REPLACE "o" WITH "z" IN File18
                        REPLACE "u" WITH "z" IN File18
                        'IF ProcessCnt = 18 THEN
                        '    PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                        '    EXIT IF
                        'ELSE
                            GoNext = 1
                        'END IF
                    END IF
    
                    IF GoNext = 1 THEN
                        GoNext = 0
                        'do something to the content
                        REPLACE "a" WITH "z" IN File19
                        REPLACE "e" WITH "z" IN File19
                        REPLACE "i" WITH "z" IN File19
                        REPLACE "o" WITH "z" IN File19
                        REPLACE "u" WITH "z" IN File19
                        'IF ProcessCnt = 19 THEN
                        '    PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                        '    EXIT IF
                        'ELSE
                            GoNext = 1
                        'END IF
                    END IF
    
                    IF GoNext = 1 THEN
                        GoNext = 0
                        'do something to the content
                        REPLACE "a" WITH "z" IN File20
                        REPLACE "e" WITH "z" IN File20
                        REPLACE "i" WITH "z" IN File20
                        REPLACE "o" WITH "z" IN File20
                        REPLACE "u" WITH "z" IN File20
                        IF ProcessCnt = 20 THEN
                            QueryPerformanceCounter qStopProcess
                            qProcessAccum = qProcessAccum + (qStopProcess - qStartProcess)
                            PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                            GOTO Leave
                        'ELSE
                        '    GoNext = 1
                        END IF
                    END IF
    
                END IF
                Leave:
            END IF
            IF giAppRunning = 1 THEN SLEEP BreakTime
        WEND
        giThread01 = 0
    END FUNCTION
    
    SUB LoadFiles
      LOCAL i01 AS LONG
    
      QueryPerformanceCounter qStartRead
    
      'just open, read, and close ProcessCnt files
      SELECT CASE ProcessCnt
          CASE 1
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 0) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File01 : CLOSE #i01
              NextPT = StartPT + ProcessCnt
              FireIt = 1
    
          CASE 2
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 0) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File01 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 1) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File02 : CLOSE #i01
              NextPT = StartPT + ProcessCnt
              FireIt = 1
    
          CASE 4
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 0) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File01 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 1) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File02 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 2) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File03 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 3) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File04 : CLOSE #i01
              NextPT = StartPT + ProcessCnt
              FireIt = 1
    
          CASE 5
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 0) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File01 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 1) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File02 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 2) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File03 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 3) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File04 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 4) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File05 : CLOSE #i01
              NextPT = StartPT + ProcessCnt
              FireIt = 1
    
          CASE 10
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 0) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File01 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 1) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File02 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 2) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File03 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 3) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File04 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 4) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File05 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 5) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File06 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 6) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File07 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 7) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File08 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 8) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File09 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 9) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File10 : CLOSE #i01
              NextPT = StartPT + ProcessCnt
              FireIt = 1
    
          CASE 20
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 0) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File01 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 1) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File02 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 2) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File03 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 3) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File04 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 4) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File05 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 5) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File06 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 6) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File07 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 7) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File08 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 8) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File09 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 9) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File10 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 10) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File11 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 11) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File12 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 12) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File13 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 13) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File14 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 14) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File15 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 15) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File16 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 16) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File17 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 17) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File18 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 18) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File19 : CLOSE #i01
    
              i01 = FREEFILE
              OPEN "threads\" + URLs(StartPT + 19) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File20 : CLOSE #i01
              NextPT = StartPT + ProcessCnt
              FireIt = 1
      END SELECT
      QueryPerformanceCounter qStopRead
      qReadAccum = qReadAccum + (qStopRead - qStartRead)
    END SUB
    
    
    SUB SaveFiles
      LOCAL i01 AS LONG
    
      QueryPerformanceCounter qStartSave
    
      SELECT CASE ProcessCnt
          CASE 1
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 00) FOR OUTPUT AS #i01 : PRINT #i01, File01; : CLOSE #i01
              File01 = ""
    
          CASE 2
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 00) FOR OUTPUT AS #i01 : PRINT #i01, File01; : CLOSE #i01
              File01 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 01) FOR OUTPUT AS #i01 : PRINT #i01, File02; : CLOSE #i01
              File02 = ""
    
          CASE 4
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 00) FOR OUTPUT AS #i01 : PRINT #i01, File01; : CLOSE #i01
              File01 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 01) FOR OUTPUT AS #i01 : PRINT #i01, File02; : CLOSE #i01
              File02 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 02) FOR OUTPUT AS #i01 : PRINT #i01, File03; : CLOSE #i01
              File03 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 03) FOR OUTPUT AS #i01 : PRINT #i01, File04; : CLOSE #i01
              File04 = ""
    
          CASE 5
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 00) FOR OUTPUT AS #i01 : PRINT #i01, File01; : CLOSE #i01
              File01 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 01) FOR OUTPUT AS #i01 : PRINT #i01, File02; : CLOSE #i01
              File02 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 02) FOR OUTPUT AS #i01 : PRINT #i01, File03; : CLOSE #i01
              File03 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 03) FOR OUTPUT AS #i01 : PRINT #i01, File04; : CLOSE #i01
              File04 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 04) FOR OUTPUT AS #i01 : PRINT #i01, File05; : CLOSE #i01
              File05 = ""
    
          CASE 10
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 00) FOR OUTPUT AS #i01 : PRINT #i01, File01; : CLOSE #i01
              File01 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 01) FOR OUTPUT AS #i01 : PRINT #i01, File02; : CLOSE #i01
              File02 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 02) FOR OUTPUT AS #i01 : PRINT #i01, File03; : CLOSE #i01
              File03 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 03) FOR OUTPUT AS #i01 : PRINT #i01, File04; : CLOSE #i01
              File04 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 04) FOR OUTPUT AS #i01 : PRINT #i01, File05; : CLOSE #i01
              File05 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 05) FOR OUTPUT AS #i01 : PRINT #i01, File06; : CLOSE #i01
              File06 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 06) FOR OUTPUT AS #i01 : PRINT #i01, File07; : CLOSE #i01
              File07 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 07) FOR OUTPUT AS #i01 : PRINT #i01, File08; : CLOSE #i01
              File08 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 08) FOR OUTPUT AS #i01 : PRINT #i01, File09; : CLOSE #i01
              File09 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 09) FOR OUTPUT AS #i01 : PRINT #i01, File10; : CLOSE #i01
              File10 = ""
    
          CASE 20
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 00) FOR OUTPUT AS #i01 : PRINT #i01, File01; : CLOSE #i01
              File01 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 01) FOR OUTPUT AS #i01 : PRINT #i01, File02; : CLOSE #i01
              File02 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 02) FOR OUTPUT AS #i01 : PRINT #i01, File03; : CLOSE #i01
              File03 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 03) FOR OUTPUT AS #i01 : PRINT #i01, File04; : CLOSE #i01
              File04 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 04) FOR OUTPUT AS #i01 : PRINT #i01, File05; : CLOSE #i01
              File05 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 05) FOR OUTPUT AS #i01 : PRINT #i01, File06; : CLOSE #i01
              File06 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 06) FOR OUTPUT AS #i01 : PRINT #i01, File07; : CLOSE #i01
              File07 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 07) FOR OUTPUT AS #i01 : PRINT #i01, File08; : CLOSE #i01
              File08 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 08) FOR OUTPUT AS #i01 : PRINT #i01, File09; : CLOSE #i01
              File09 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 09) FOR OUTPUT AS #i01 : PRINT #i01, File10; : CLOSE #i01
              File10 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 10) FOR OUTPUT AS #i01 : PRINT #i01, File11; : CLOSE #i01
              File11 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 11) FOR OUTPUT AS #i01 : PRINT #i01, File12; : CLOSE #i01
              File12 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 12) FOR OUTPUT AS #i01 : PRINT #i01, File13; : CLOSE #i01
              File13 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 13) FOR OUTPUT AS #i01 : PRINT #i01, File14; : CLOSE #i01
              File14 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 14) FOR OUTPUT AS #i01 : PRINT #i01, File15; : CLOSE #i01
              File15 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 15) FOR OUTPUT AS #i01 : PRINT #i01, File16; : CLOSE #i01
              File16 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 16) FOR OUTPUT AS #i01 : PRINT #i01, File17; : CLOSE #i01
              File17 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 17) FOR OUTPUT AS #i01 : PRINT #i01, File18; : CLOSE #i01
              File18 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 18) FOR OUTPUT AS #i01 : PRINT #i01, File19; : CLOSE #i01
              File19 = ""
    
              i01 = FREEFILE
              OPEN "threads_formatted\" + URLs(StartPT + 19) FOR OUTPUT AS #i01 : PRINT #i01, File20; : CLOSE #i01
              File20 = ""
      END SELECT
      QueryPerformanceCounter qStopSave
      qSaveAccum = qSaveAccum + (qStopSave - qStartSave)
    
    END SUB
    Last edited by Jim Fritts; 26 Aug 2020, 03:32 AM.

    Comment


      #3
      Version V5 produces 2000 processed files in ~11 seconds. Demonstrates a simplified parallel processing technique. A more advanced method like what was used in the original version could drop the processing time further. In this example any selection below 20 processes results in only 1 thread doing the file processing and a slower Overall Time.
      Comments here please.

      Code:
      'Compilable Example:
      #COMPILE EXE "threadsV5.exe"
      #DIM ALL
      
      'Updated by Jim Fritts on 2020-AUG-25
      'Designed to run on Windows 10 2004
      'Platform: PBWIN10 and J. Roca includes
      'To use this program as is you will need to download Gary Beene's sample files from
      'http://www.garybeene.com/files/threads.zip
      'Replace his Threads.bas with this app.
      'As a comparison Gary's unmodified code ran 6.1 minutes for 2000 files.
      'My modified version uses 11 threads and ran 12.4 seconds for 2000 files.
      'This version V5 processes 2000 files in ~11 seconds. See Overall Time.
      'FileTotal
      'Comments here please:
      'https://forum.powerbasic.com/forum/user-to-user-discussions/programming/798049-effect-of-multiple-threads?p=798321#post798321
      
      'NOTE:
      ' The first time through after the app is launched the results are longer.
      ' I created 2000 duplicate files so the app could be tested on 4000 files.
      ' To process more files than 2000 change this FileTotal which should be in
      ' multiples of ProcessCnt.
      
      ' Be advised that on my system if I process 5800 files and above my HDD
      ' goes into saturation which slows down all processes.
      
      'Time is in seconds
      ' Files Processed 2,000  Save and load are in a thread now
      ' Processes       20
      ' Read Time       0.918
      ' Process Time    9.982   << more time before parallel processing was added
      ' Save Time       3.586
      ' Component Time 14.486
      ' Overall Time   14.9     << more time before parallel processing was added
      ' Delta Time      0.414
      ' Time per file   0.00745
      
      ' Files Processed 2,000  Simple Parallel processing of 20 files using 2 threads
      ' Processes       20
      ' Read Time       0.955
      ' Process Time    5.137   << less time (a measure of the slowest processing thread)
      ' Save Time       3.714
      ' Component Time  9.806
      ' Overall Time   11.049   << less time
      ' Delta Time      1.243
      ' Time per file   0.00552
      
      
      #DEBUG ERROR ON
      #DEBUG DISPLAY ON
      
      %Unicode = 1
      #INCLUDE "Win32API.inc"
      
      #RESOURCE ICON logo, "index.ico"
      
      ENUM Equates SINGULAR
         IDC_Stop = 1500
         IDC_Start
         IDC_Next
         IDC_Finished
         IDC_Display
         IDC_SaveAndLoad
         IDC_Label_01
         IDC_ProcessOne
         IDC_ProcessTwo
         IDC_ProcessFour
         IDC_ProcessFive
         IDC_ProcessTen
         IDC_ProcessTwenty
         IDC_Label_02
         IDC_Text_01
         IDC_Check
      
      END ENUM
      
      GLOBAL hDlg          AS LONG
      GLOBAL StopAction    AS LONG
      GLOBAL URLsPerThread AS LONG
      GLOBAL ThreadsCount  AS LONG
      GLOBAL hThread01, _
             hThread02, _
             hThread03, _
             hThread04, _
             hThread05, _
             hThread06, _
             hThread07, _
             hThread08, _
             hThread09, _
             hThread10, _
             hThreadSaveLoad  AS DWORD
      GLOBAL URLS()        AS STRING    'file name array shared between main app and storage thread
      GLOBAL StartTime     AS STRING
      
      GLOBAL qFreq         AS QUAD
      GLOBAL qStart        AS QUAD
      GLOBAL qStop         AS QUAD
      
      GLOBAL qStartRead    AS QUAD
      GLOBAL qStopRead     AS QUAD
      GLOBAL qReadAccum    AS QUAD
      
      GLOBAL giPT01Completed AS LONG
      GLOBAL giPT02Completed AS LONG
      GLOBAL qProcess        AS QUAD
      GLOBAL qStartProcess01 AS QUAD
      GLOBAL qStopProcess01  AS QUAD
      GLOBAL qProcessAccum01 AS QUAD
      GLOBAL qStartProcess02 AS QUAD
      GLOBAL qStopProcess02  AS QUAD
      GLOBAL qProcessAccum02 AS QUAD
      
      GLOBAL qStartSave    AS QUAD
      GLOBAL qStopSave     AS QUAD
      GLOBAL qSaveAccum    AS QUAD
      
      GLOBAL StartPT       AS LONG  'jumps by ProcessCnt each time
      GLOBAL NextPT        AS LONG
      GLOBAL ProcessCnt    AS LONG
      GLOBAL FireIt01      AS LONG
      GLOBAL FireIt02      AS LONG
      
      GLOBAL giWipedFolder AS LONG
      GLOBAL SaveLoadIt    AS LONG
      
      GLOBAL giThread01    AS LONG
      GLOBAL giThread02    AS LONG
      GLOBAL giThreadSaveLoad AS LONG
      
      GLOBAL File01        AS STRING
      GLOBAL File02        AS STRING
      GLOBAL File03        AS STRING
      GLOBAL File04        AS STRING
      GLOBAL File05        AS STRING
      GLOBAL File06        AS STRING
      GLOBAL File07        AS STRING
      GLOBAL File08        AS STRING
      GLOBAL File09        AS STRING
      GLOBAL File10        AS STRING
      
      GLOBAL File11        AS STRING
      GLOBAL File12        AS STRING
      GLOBAL File13        AS STRING
      GLOBAL File14        AS STRING
      GLOBAL File15        AS STRING
      GLOBAL File16        AS STRING
      GLOBAL File17        AS STRING
      GLOBAL File18        AS STRING
      GLOBAL File19        AS STRING
      GLOBAL File20        AS STRING
      
      GLOBAL giAppRunning AS LONG
      GLOBAL FileTotal    AS LONG
      GLOBAL BreakTime    AS LONG
      
      FUNCTION PBMAIN() AS LONG
         LOCAL i    AS LONG
         LOCAL Time AS TIMECAPS
      
         TimeGetDevCaps ( Time, SIZEOF(Time) )
         timeBeginPeriod (Time.wPeriodMin)
         SLEEP 16
      
         'These settings produce a Time per file of ~0.00546 seconds
         FileTotal = 2000 '< Change this to the number of files you want to process. It must be in multiples of ProcessCnt
         ProcessCnt = 20  '< It is defaulted to 20 files at a time to give the best results. This is program selectable.
         BreakTime = 1 '10'< How long the threads wait per loop when not performing a task.
      
         'Be advised that on my system if I process 5800 files and above my HDD
         'goes into saturation which slows down all processes.
      
         DIALOG DEFAULT FONT "Tahoma",12, 0
         DIALOG NEW PIXELS, 0, "Process Files",,,260,305, %WS_OVERLAPPEDWINDOW TO hDlg
         DIALOG SET ICON hDlg, "logo"
         CONTROL ADD BUTTON, hDlg, %IDC_Start,"Start", 10,10,70,25
         CONTROL ADD BUTTON, hDlg, %IDC_Stop,"Stop", 90,10,70,25
         CONTROL ADD BUTTON, hDlg, %IDC_Check,"Check", 170,10,70,25
      
         CONTROL DISABLE hDlg, %IDC_Stop
         CONTROL DISABLE hDlg, %IDC_Check
      
         'Processes per thread
         CONTROL ADD LABEL, hDlg, %IDC_Label_01, "Select processes per thread", 10,40,235,25, %SS_CENTER
         CONTROL ADD CHECKBOX, hDlg, %IDC_ProcessOne   , "1", 10,65,40,25, %WS_GROUP OR %WS_TABSTOP OR %BS_PUSHLIKE
         CONTROL ADD CHECKBOX, hDlg, %IDC_ProcessTwo   , "2", 50,65,40,25, %WS_TABSTOP OR %BS_PUSHLIKE
         CONTROL ADD CHECKBOX, hDlg, %IDC_ProcessFour  , "4", 90,65,40,25, %WS_TABSTOP OR %BS_PUSHLIKE
         CONTROL ADD CHECKBOX, hDlg, %IDC_ProcessFive  , "5",130,65,40,25, %WS_TABSTOP OR %BS_PUSHLIKE
         CONTROL ADD CHECKBOX, hDlg, %IDC_ProcessTen   ,"10",170,65,40,25, %WS_TABSTOP OR %BS_PUSHLIKE
         CONTROL ADD CHECKBOX, hDlg, %IDC_ProcessTwenty,"20",210,65,40,25, %WS_TABSTOP OR %BS_PUSHLIKE
         CONTROL ADD LABEL, hDlg, %IDC_Label_02, "Results: Times in seconds", 10,90,235,25, %SS_CENTER
         CONTROL ADD TEXTBOX, hDlg, %IDC_Text_01, "", 10,115,240,180, %ES_MULTILINE OR %ES_AUTOHSCROLL OR %ES_AUTOVSCROLL
      
         SELECT CASE ProcessCnt
             CASE 1,2,4,5,10,20
                 IF ProcessCnt = 20 THEN
                     CONTROL SET CHECK hDlg, %IDC_ProcessTwenty, 1
                 END IF
                 IF ProcessCnt = 10 THEN
                     CONTROL SET CHECK hDlg, %IDC_ProcessTen, 1
                 END IF
                 IF ProcessCnt = 5 THEN
                     CONTROL SET CHECK hDlg, %IDC_ProcessFive, 1
                 END IF
                 IF ProcessCnt = 4 THEN
                     CONTROL SET CHECK hDlg, %IDC_ProcessFour, 1
                 END IF
                 IF ProcessCnt = 2 THEN
                     CONTROL SET CHECK hDlg, %IDC_ProcessTwo, 1
                 END IF
                 IF ProcessCnt = 1 THEN
                     CONTROL SET CHECK hDlg, %IDC_ProcessOne, 1
                 END IF
      
             CASE ELSE
                 ? "The process count is not set correctly!" & $CRLF & _
                   "ProcessCnt should be 1, 2, 4, 5, 10, or 20." & $CRLF & $CRLF & _
                   "This program will close."
                 EXIT FUNCTION
         END SELECT
      
         DIALOG SHOW MODAL hDlg CALL DlgProc
      END FUNCTION
      
      CALLBACK FUNCTION DlgProc() AS LONG
         SELECT CASE CB.MSG
            CASE %WM_INITDIALOG
                IF ISFALSE ISFOLDER("threads_formatted") THEN MKDIR "threads_formatted"
                'Settings_INI "get"
                CALL LoadURLs      '1 to FileTotal
                QueryPerformanceFrequency qFreq
                giAppRunning = 1
                StartPT = 1
                'remove formatted files on first run
                IF DIR$(EXE.PATH$ & "threads_formatted\*.HTM") <> "" AND giWipedFolder = 0 THEN
                    KILL EXE.PATH$ & "threads_formatted\*.HTM"
                    giWipedFolder = 1
                END IF
                CALL CreateTheThreads
      
            CASE %WM_DESTROY
                winbeep(3000, 75)
                giAppRunning = 0
                Settings_INI "save"
      
            CASE %WM_COMMAND
                SELECT CASE CB.CTL
                    CASE %IDC_ProcessOne
                        CONTROL SET TEXT hDlg, %IDC_Text_01, ""
                        CONTROL SET CHECK hDlg, %IDC_ProcessTwenty, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessTen, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessFive, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessFour, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessTwo, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessOne, 1
                        ProcessCnt = 1
      
                    CASE %IDC_ProcessTwo
                        CONTROL SET TEXT hDlg, %IDC_Text_01, ""
                        CONTROL SET CHECK hDlg, %IDC_ProcessTwenty, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessTen, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessFive, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessFour, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessOne, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessTwo, 1
                        ProcessCnt = 2
      
                    CASE %IDC_ProcessFour
                        CONTROL SET TEXT hDlg, %IDC_Text_01, ""
                        CONTROL SET CHECK hDlg, %IDC_ProcessTwenty, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessTen, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessFive, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessOne, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessTwo, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessFour, 1
                        ProcessCnt = 4
      
                    CASE %IDC_ProcessFive
                        CONTROL SET TEXT hDlg, %IDC_Text_01, ""
                        CONTROL SET CHECK hDlg, %IDC_ProcessTwenty, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessTen, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessFour, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessOne, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessTwo, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessFive, 1
                        ProcessCnt = 5
      
                    CASE %IDC_ProcessTen
                        CONTROL SET TEXT hDlg, %IDC_Text_01, ""
                        CONTROL SET CHECK hDlg, %IDC_ProcessTwenty, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessFive, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessFour, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessOne, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessTwo, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessTen, 1
                        ProcessCnt = 10
      
                    CASE %IDC_ProcessTwenty
                        CONTROL SET TEXT hDlg, %IDC_Text_01, ""
                        CONTROL SET CHECK hDlg, %IDC_ProcessTen, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessFive, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessFour, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessOne, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessTwo, 0
                        CONTROL SET CHECK hDlg, %IDC_ProcessTwenty, 1
                        ProcessCnt = 20
      
                    CASE %IDC_Check
                        CONTROL SET TEXT hDlg, %IDC_Text_01, "Current location=" & STR$(StartPT)
      
                    CASE %IDC_Stop     : StopAction = 1
                        CONTROL SET TEXT hDlg, %IDC_Text_01, "Current location=" & STR$(StartPT)
                        CONTROL ENABLE hDlg, %IDC_Start
                        CONTROL DISABLE hDlg, %IDC_Stop
                        CONTROL DISABLE hDlg, %IDC_Check
                        DIALOG SET TEXT hDlg, "Process Files"
      
                    CASE %IDC_Start    : ThreadsCount = ProcessCnt  : URLsPerThread = 1  : ProcessFiles
                    CASE %IDC_SaveAndLoad
                        SaveLoadIt = 1
      
                    CASE %IDC_Display
                        QueryPerformanceCounter   qStop
                        IF qProcessAccum01 > qProcessAccum02 THEN
                            qProcess = qProcessAccum01
                        ELSE
                            qProcess = qProcessAccum02
                        END IF
                        CONTROL SET TEXT hDlg, %IDC_Text_01, _
                              " Files Processed " & $TAB & FORMAT$(StartPT -1, "##,##0") & $CRLF & _
                              " Processes" & $TAB & LTRIM$(STR$(ProcessCnt)) & $CRLF & _
                              " Read Time " & $TAB + FORMAT$(qReadAccum/qFreq,"###.###") & $CRLF & _
                              " Process Time " & $TAB + FORMAT$(qProcess/qFreq,"###.###") & $CRLF & _
                              " Save Time " & $TAB + FORMAT$(qSaveAccum/qFreq,"###.###") & $CRLF & _
                              " Component Time " & $TAB + FORMAT$((qReadAccum + qProcess + qSaveAccum)/qFreq,"###.###") & $CRLF & _
                              " Overall Time " & $TAB + FORMAT$((qStop-qStart)/qFreq,"###.###") & $CRLF & _
                              " Delta Time " & $TAB + FORMAT$((qStop-qStart - (qReadAccum + qProcess + qSaveAccum))/qFreq,"###.###") & $CRLF & _
                              " Time per file " & $TAB + FORMAT$(((qStop-qStart)/FileTotal)/qFreq,"###.#####")
      
                    CASE %IDC_Finished
                        'there will be a small time delay here
                        DIALOG SET TEXT hDlg, "Completed"
      
                        CONTROL ENABLE hDlg, %IDC_Start
                        CONTROL DISABLE hDlg, %IDC_Stop
                        CONTROL DISABLE hDlg, %IDC_Check
                        CONTROL ENABLE hDlg, %IDC_ProcessOne
                        CONTROL ENABLE hDlg, %IDC_ProcessTwo
                        CONTROL ENABLE hDlg, %IDC_ProcessFour
                        CONTROL ENABLE hDlg, %IDC_ProcessFive
                        CONTROL ENABLE hDlg, %IDC_ProcessTen
                        CONTROL ENABLE hDlg, %IDC_ProcessTwenty
                        PostMessage hDlg, %WM_COMMAND, %IDC_Display, 0
      
                END SELECT
         END SELECT
      END FUNCTION
      
      SUB LoadURLs
        LOCAL i AS LONG
        REDIM URLs(1 TO FileTotal)
      
        URLs(1) = DIR$("threads\*.htm")
        FOR i = 2 TO UBOUND(URLs) : URLs(i) = DIR$(NEXT) : NEXT i
      END SUB
      
      
      SUB Settings_INI(Task$)
         LOCAL xResult, yResult, tempZ, INIFileName AS WSTRINGZ * %MAX_PATH, WinPla AS WindowPlacement
         'set ini filename
         INIFileName = EXE.PATH$ + "threads.ini"
      
         IF Task$ = "get" THEN
      
            'get dialog width/height from INI file and use to set Dialog size
            GetPrivateProfileString "All", "Width", "1070", xResult, %MAX_PATH, INIFileName
            GetPrivateProfileString "All", "Height", "125", yResult, %MAX_PATH, INIFileName
            DIALOG SET SIZE hDlg,VAL(xResult), VAL(yResult)   'width/height
      
            'default position should be centered on screen
            LOCAL DefaultX, DefaultY, wDeskTop, hDeskTop AS LONG
            DESKTOP GET CLIENT TO wDeskTop, hDeskTop
            DefaultX = (wDeskTop-VAL(xResult))/2
            DefaultY = (hDeskTop-VAL(yResult))/2
      
            'get dialog top/left from INI file and use to set Dialog location
            Getprivateprofilestring "All", "Left", STR$(DefaultX), xResult, %MAX_PATH, INIFileName
            Getprivateprofilestring "All", "Top", STR$(DefaultY), yResult, %MAX_PATH, INIFileName
            DIALOG SET LOC hDlg, VAL(xResult), VAL(yResult)   'left/top
      
         END IF
      
         IF Task$ = "save" THEN
            'If Len(Dir$(INIFileName)) Then Kill INIFileName
            'save dialog size/location unless minimized or maximized
            WinPla.length = SIZEOF(WinPla)
            GetWindowPlacement hDlg, WinPla
            WritePrivateProfileString "All", "Left", STR$(WinPla.rcNormalPosition.nLeft), INIFileName
            WritePrivateProfileString "All", "Top", STR$(WinPla.rcNormalPosition.nTop), INIFileName
            WritePrivateProfileString "All", "Width", STR$(WinPla.rcNormalPosition.nRight - WinPla.rcNormalPosition.nLeft), INIFileName
            WritePrivateProfileString "All", "Height", STR$(WinPla.rcNormalPosition.nBottom - WinPla.rcNormalPosition.nTop), INIFileName
            WritePrivateProfileString "All", "MinMaxState", STR$(WinPla.showCmd), INIFileName
      
         END IF
      END SUB
      
      SUB ProcessFiles
        LOCAL i AS LONG
      
        qReadAccum = 0
        qProcessAccum01 = 0
        qProcessAccum02 = 0
        qSaveAccum = 0
        qStart = 0
        qStop = 0
      
        StopAction = 0
        StartPT = 1
        NextPT = 1
        StartTime = TIME$
        QueryPerformanceCounter   qStart
        DIALOG SET TEXT hDlg, "Processing..."
      
        CONTROL SET TEXT hDlg, %IDC_Text_01, ""
        CONTROL DISABLE hDlg, %IDC_Start
        CONTROL ENABLE hDlg, %IDC_Stop
        CONTROL ENABLE hDlg, %IDC_Check
      
        CONTROL DISABLE hDlg, %IDC_ProcessOne
        CONTROL DISABLE hDlg, %IDC_ProcessTwo
        CONTROL DISABLE hDlg, %IDC_ProcessFour
        CONTROL DISABLE hDlg, %IDC_ProcessFive
        CONTROL DISABLE hDlg, %IDC_ProcessTen
        CONTROL DISABLE hDlg, %IDC_ProcessTwenty
      
        CALL LoadFiles
      END SUB
      
      
      SUB CreateTheThreads
      
        StopAction = 0
        'Split processing the files between 2 threads
        IF giThread01 = 0 THEN
            THREAD CREATE FT01(999) TO hThread01   : THREAD CLOSE hThread01 TO hThread01
        END IF
        IF giThread02 = 0 THEN
            THREAD CREATE FT02(999) TO hThread02   : THREAD CLOSE hThread02 TO hThread02
        END IF
      
        'Do Save and Load files in its own thread
        IF giThreadSaveLoad = 0 THEN
            THREAD CREATE SaveAndLoadThread(999) TO hThreadSaveLoad   : THREAD CLOSE hThreadSaveLoad TO hThreadSaveLoad
        END IF
        'wait for threads to start running
        SLEEP 20
      END SUB
      
      
      SUB SaveAndLoad
        IF StartPt > UBOUND(URLS()) THEN
            PostMessage hDlg, %WM_COMMAND, %IDC_Finished, 0
            EXIT SUB
        END IF
      
        CALL SaveFiles
      
        StartPT = NextPT
      
        IF StartPT > UBOUND(URLS()) THEN
            PostMessage hDlg, %WM_COMMAND, %IDC_Finished, 0
            EXIT SUB
        END IF
      
        SELECT CASE StartPT
            CASE 5001, _
                 10001, _
                 15001, _
                 20001, _
                 25001, _
                 30001, _
                 35001, _
                 40001, _
                 45001, _
                 50001
                PostMessage hDlg, %WM_COMMAND, %IDC_Display, 0
                SLEEP 3000
                '? "here"
        END SELECT
      
        CALL LoadFiles
      END SUB
      
      THREAD FUNCTION SaveAndLoadThread(BYVAL x AS LONG) AS LONG
          LOCAL Result AS LONG
          giThreadSaveLoad = 1
      
          WHILE giAppRunning = 1
              IF StopAction = 1 THEN
                  SaveLoadIt = 0
              END IF
      
              IF SaveLoadIt = 1 THEN
                  SaveLoadIt = 0
                  Result = SetPriorityClass(GetCurrentProcess(), %REALTIME_PRIORITY_CLASS)
                  CALL SaveAndLoad
                  Result = SetPriorityClass(GetCurrentProcess(), %NORMAL_PRIORITY_CLASS)
              END IF
              IF giAppRunning = 1 THEN SLEEP BreakTime
          WEND
      
          giThreadSaveLoad = 1
      END FUNCTION
      
      'Example of Parallel processing with 2 sequential threads
      
      THREAD FUNCTION FT01(BYVAL x AS LONG) AS LONG
          LOCAL GoNext AS LONG
      
          giThread01 = 1
      
          WHILE giAppRunning = 1
              IF FireIt01 = 1 THEN
                  QueryPerformanceCounter qStartProcess01
                  FireIt01 = 0
                  IF ProcessCnt = 20 THEN
                      FireIt02 = 1
                  END IF
                  GoNext = 1
                  IF StopAction = 0 AND giAppRunning = 1 THEN
                      IF GoNext = 1 THEN
                          GoNext = 0
                          'do something to the content
                          REPLACE "a" WITH "z" IN File01
                          REPLACE "e" WITH "z" IN File01
                          REPLACE "i" WITH "z" IN File01
                          REPLACE "o" WITH "z" IN File01
                          REPLACE "u" WITH "z" IN File01
                          IF ProcessCnt = 1 THEN
                              QueryPerformanceCounter qStopProcess01
                              qProcessAccum01 = qProcessAccum01 + (qStopProcess01 - qStartProcess01)
                              PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                              GOTO Leave
                          ELSE
                              GoNext = 1
                          END IF
                      END IF
      
                      IF GoNext = 1 THEN
                          GoNext = 0
                          'do something to the content
                          REPLACE "a" WITH "z" IN File02
                          REPLACE "e" WITH "z" IN File02
                          REPLACE "i" WITH "z" IN File02
                          REPLACE "o" WITH "z" IN File02
                          REPLACE "u" WITH "z" IN File02
                          IF ProcessCnt = 2 THEN
                              QueryPerformanceCounter qStopProcess01
                              qProcessAccum01 = qProcessAccum01 + (qStopProcess01 - qStartProcess01)
                              PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                              GOTO Leave
                          ELSE
                              GoNext = 1
                          END IF
                      END IF
      
                      IF GoNext = 1 THEN
                          GoNext = 0
                          'do something to the content
                          REPLACE "a" WITH "z" IN File03
                          REPLACE "e" WITH "z" IN File03
                          REPLACE "i" WITH "z" IN File03
                          REPLACE "o" WITH "z" IN File03
                          REPLACE "u" WITH "z" IN File03
                          GoNext = 1
                      END IF
      
                      IF GoNext = 1 THEN
                          GoNext = 0
                          'do something to the content
                          REPLACE "a" WITH "z" IN File04
                          REPLACE "e" WITH "z" IN File04
                          REPLACE "i" WITH "z" IN File04
                          REPLACE "o" WITH "z" IN File04
                          REPLACE "u" WITH "z" IN File04
                          IF ProcessCnt = 4 THEN
                              QueryPerformanceCounter qStopProcess01
                              qProcessAccum01 = qProcessAccum01 + (qStopProcess01 - qStartProcess01)
                              PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                              GOTO Leave
                          ELSE
                              GoNext = 1
                          END IF
                      END IF
      
                      IF GoNext = 1 THEN
                          GoNext = 0
                          'do something to the content
                          REPLACE "a" WITH "z" IN File05
                          REPLACE "e" WITH "z" IN File05
                          REPLACE "i" WITH "z" IN File05
                          REPLACE "o" WITH "z" IN File05
                          REPLACE "u" WITH "z" IN File05
                          IF ProcessCnt = 5 THEN
                              QueryPerformanceCounter qStopProcess01
                              qProcessAccum01 = qProcessAccum01 + (qStopProcess01 - qStartProcess01)
                              PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                              GOTO Leave
                          ELSE
                              GoNext = 1
                          END IF
                      END IF
      
                      IF GoNext = 1 THEN
                          GoNext = 0
                          'do something to the content
                          REPLACE "a" WITH "z" IN File06
                          REPLACE "e" WITH "z" IN File06
                          REPLACE "i" WITH "z" IN File06
                          REPLACE "o" WITH "z" IN File06
                          REPLACE "u" WITH "z" IN File06
                          GoNext = 1
                      END IF
      
                      IF GoNext = 1 THEN
                          GoNext = 0
                          'do something to the content
                          REPLACE "a" WITH "z" IN File07
                          REPLACE "e" WITH "z" IN File07
                          REPLACE "i" WITH "z" IN File07
                          REPLACE "o" WITH "z" IN File07
                          REPLACE "u" WITH "z" IN File07
                          GoNext = 1
                      END IF
      
                      IF GoNext = 1 THEN
                          GoNext = 0
                          'do something to the content
                          REPLACE "a" WITH "z" IN File08
                          REPLACE "e" WITH "z" IN File08
                          REPLACE "i" WITH "z" IN File08
                          REPLACE "o" WITH "z" IN File08
                          REPLACE "u" WITH "z" IN File08
                          GoNext = 1
                      END IF
      
                      IF GoNext = 1 THEN
                          GoNext = 0
                          'do something to the content
                          REPLACE "a" WITH "z" IN File09
                          REPLACE "e" WITH "z" IN File09
                          REPLACE "i" WITH "z" IN File09
                          REPLACE "o" WITH "z" IN File09
                          REPLACE "u" WITH "z" IN File09
                          GoNext = 1
                      END IF
      
                      IF GoNext = 1 THEN
                          GoNext = 0
                          'do something to the content
                          REPLACE "a" WITH "z" IN File10
                          REPLACE "e" WITH "z" IN File10
                          REPLACE "i" WITH "z" IN File10
                          REPLACE "o" WITH "z" IN File10
                          REPLACE "u" WITH "z" IN File10
                          IF ProcessCnt = 10 THEN
                              QueryPerformanceCounter qStopProcess01
                              qProcessAccum01 = qProcessAccum01 + (qStopProcess01 - qStartProcess01)
                              PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                              GOTO Leave
                          ELSE
                              QueryPerformanceCounter qStopProcess01
                              qProcessAccum01 = qProcessAccum01 + (qStopProcess01 - qStartProcess01)
                              giPT01Completed = 1
                              IF giPT01Completed = 1 AND giPT02Completed = 1 THEN
                                  giPT01Completed = 0
                                  giPT02Completed = 0
                                  PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                              END IF
                          END IF
                      END IF
      
                  END IF
                  Leave:
              END IF
              IF giAppRunning = 1 THEN SLEEP BreakTime
          WEND
          giThread01 = 0
      END FUNCTION
      
      'Example of Parallel processing with 2 sequential threads
      
      THREAD FUNCTION FT02(BYVAL x AS LONG) AS LONG
          LOCAL GoNext AS LONG
      
          giThread02 = 1
      
          WHILE giAppRunning = 1
              IF FireIt02 = 1 THEN
                  QueryPerformanceCounter qStartProcess02
                  FireIt02 = 0
                  GoNext = 1
                  IF StopAction = 0 AND giAppRunning = 1 THEN
                      IF GoNext = 1 THEN
                          GoNext = 0
                          'do something to the content
                          REPLACE "a" WITH "z" IN File11
                          REPLACE "e" WITH "z" IN File11
                          REPLACE "i" WITH "z" IN File11
                          REPLACE "o" WITH "z" IN File11
                          REPLACE "u" WITH "z" IN File11
                          GoNext = 1
                      END IF
      
                      IF GoNext = 1 THEN
                          GoNext = 0
                          'do something to the content
                          REPLACE "a" WITH "z" IN File12
                          REPLACE "e" WITH "z" IN File12
                          REPLACE "i" WITH "z" IN File12
                          REPLACE "o" WITH "z" IN File12
                          REPLACE "u" WITH "z" IN File12
                          GoNext = 1
                      END IF
      
                      IF GoNext = 1 THEN
                          GoNext = 0
                          'do something to the content
                          REPLACE "a" WITH "z" IN File13
                          REPLACE "e" WITH "z" IN File13
                          REPLACE "i" WITH "z" IN File13
                          REPLACE "o" WITH "z" IN File13
                          REPLACE "u" WITH "z" IN File13
                          GoNext = 1
                      END IF
      
                      IF GoNext = 1 THEN
                          GoNext = 0
                          'do something to the content
                          REPLACE "a" WITH "z" IN File14
                          REPLACE "e" WITH "z" IN File14
                          REPLACE "i" WITH "z" IN File14
                          REPLACE "o" WITH "z" IN File14
                          REPLACE "u" WITH "z" IN File14
                          GoNext = 1
                      END IF
      
                      IF GoNext = 1 THEN
                          GoNext = 0
                          'do something to the content
                          REPLACE "a" WITH "z" IN File15
                          REPLACE "e" WITH "z" IN File15
                          REPLACE "i" WITH "z" IN File15
                          REPLACE "o" WITH "z" IN File15
                          REPLACE "u" WITH "z" IN File15
                          GoNext = 1
                      END IF
      
                      IF GoNext = 1 THEN
                          GoNext = 0
                          'do something to the content
                          REPLACE "a" WITH "z" IN File16
                          REPLACE "e" WITH "z" IN File16
                          REPLACE "i" WITH "z" IN File16
                          REPLACE "o" WITH "z" IN File16
                          REPLACE "u" WITH "z" IN File16
                          GoNext = 1
                      END IF
      
                      IF GoNext = 1 THEN
                          GoNext = 0
                          'do something to the content
                          REPLACE "a" WITH "z" IN File17
                          REPLACE "e" WITH "z" IN File17
                          REPLACE "i" WITH "z" IN File17
                          REPLACE "o" WITH "z" IN File17
                          REPLACE "u" WITH "z" IN File17
                          GoNext = 1
                      END IF
      
                      IF GoNext = 1 THEN
                          GoNext = 0
                          'do something to the content
                          REPLACE "a" WITH "z" IN File18
                          REPLACE "e" WITH "z" IN File18
                          REPLACE "i" WITH "z" IN File18
                          REPLACE "o" WITH "z" IN File18
                          REPLACE "u" WITH "z" IN File18
                          GoNext = 1
                      END IF
      
                      IF GoNext = 1 THEN
                          GoNext = 0
                          'do something to the content
                          REPLACE "a" WITH "z" IN File19
                          REPLACE "e" WITH "z" IN File19
                          REPLACE "i" WITH "z" IN File19
                          REPLACE "o" WITH "z" IN File19
                          REPLACE "u" WITH "z" IN File19
                          GoNext = 1
                      END IF
      
                      IF GoNext = 1 THEN
                          GoNext = 0
                          'do something to the content
                          REPLACE "a" WITH "z" IN File20
                          REPLACE "e" WITH "z" IN File20
                          REPLACE "i" WITH "z" IN File20
                          REPLACE "o" WITH "z" IN File20
                          REPLACE "u" WITH "z" IN File20
                          IF ProcessCnt = 20 THEN
                              QueryPerformanceCounter qStopProcess02
                              qProcessAccum02 = qProcessAccum02 + (qStopProcess02 - qStartProcess02)
                              giPT02Completed = 1
                              IF giPT01Completed = 1 AND giPT02Completed = 1 THEN
                                  giPT01Completed = 0
                                  giPT02Completed = 0
                                  PostMessage hDlg, %WM_COMMAND, %IDC_SaveAndLoad, 0
                              END IF
                              GOTO Leave
                          END IF
                      END IF
      
                  END IF
                  Leave:
              END IF
              IF giAppRunning = 1 THEN SLEEP BreakTime
          WEND
          giThread02 = 0
      END FUNCTION
      
      SUB LoadFiles
        LOCAL i01 AS LONG
      
        QueryPerformanceCounter qStartRead
      
        'just open, read, and close ProcessCnt files
        SELECT CASE ProcessCnt
            CASE 1
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 0) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File01 : CLOSE #i01
                NextPT = StartPT + ProcessCnt
                FireIt01 = 1
      
            CASE 2
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 0) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File01 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 1) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File02 : CLOSE #i01
                NextPT = StartPT + ProcessCnt
                FireIt01 = 1
      
            CASE 4
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 0) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File01 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 1) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File02 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 2) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File03 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 3) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File04 : CLOSE #i01
                NextPT = StartPT + ProcessCnt
                FireIt01 = 1
      
            CASE 5
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 0) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File01 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 1) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File02 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 2) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File03 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 3) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File04 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 4) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File05 : CLOSE #i01
                NextPT = StartPT + ProcessCnt
                FireIt01 = 1
      
            CASE 10
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 0) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File01 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 1) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File02 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 2) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File03 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 3) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File04 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 4) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File05 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 5) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File06 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 6) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File07 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 7) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File08 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 8) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File09 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 9) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File10 : CLOSE #i01
                NextPT = StartPT + ProcessCnt
                FireIt01 = 1
      
            CASE 20
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 0) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File01 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 1) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File02 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 2) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File03 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 3) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File04 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 4) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File05 : CLOSE #i01
      
                'SLEEP 0
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 5) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File06 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 6) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File07 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 7) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File08 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 8) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File09 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 9) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File10 : CLOSE #i01
      
                'SLEEP 0
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 10) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File11 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 11) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File12 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 12) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File13 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 13) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File14 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 14) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File15 : CLOSE #i01
      
                'SLEEP 0
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 15) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File16 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 16) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File17 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 17) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File18 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 18) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File19 : CLOSE #i01
      
                i01 = FREEFILE
                OPEN "threads\" + URLs(StartPT + 19) FOR BINARY AS #i01 : GET$ #i01, LOF(i01), File20 : CLOSE #i01
                NextPT = StartPT + ProcessCnt
                FireIt01 = 1
        END SELECT
        QueryPerformanceCounter qStopRead
        qReadAccum = qReadAccum + (qStopRead - qStartRead)
      END SUB
      
      
      SUB SaveFiles
        LOCAL i01 AS LONG
      
        QueryPerformanceCounter qStartSave
      
        SELECT CASE ProcessCnt
            CASE 1
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 00) FOR OUTPUT AS #i01 : PRINT #i01, File01; : CLOSE #i01
                File01 = ""
      
            CASE 2
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 00) FOR OUTPUT AS #i01 : PRINT #i01, File01; : CLOSE #i01
                File01 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 01) FOR OUTPUT AS #i01 : PRINT #i01, File02; : CLOSE #i01
                File02 = ""
      
            CASE 4
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 00) FOR OUTPUT AS #i01 : PRINT #i01, File01; : CLOSE #i01
                File01 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 01) FOR OUTPUT AS #i01 : PRINT #i01, File02; : CLOSE #i01
                File02 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 02) FOR OUTPUT AS #i01 : PRINT #i01, File03; : CLOSE #i01
                File03 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 03) FOR OUTPUT AS #i01 : PRINT #i01, File04; : CLOSE #i01
                File04 = ""
      
            CASE 5
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 00) FOR OUTPUT AS #i01 : PRINT #i01, File01; : CLOSE #i01
                File01 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 01) FOR OUTPUT AS #i01 : PRINT #i01, File02; : CLOSE #i01
                File02 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 02) FOR OUTPUT AS #i01 : PRINT #i01, File03; : CLOSE #i01
                File03 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 03) FOR OUTPUT AS #i01 : PRINT #i01, File04; : CLOSE #i01
                File04 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 04) FOR OUTPUT AS #i01 : PRINT #i01, File05; : CLOSE #i01
                File05 = ""
      
            CASE 10
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 00) FOR OUTPUT AS #i01 : PRINT #i01, File01; : CLOSE #i01
                File01 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 01) FOR OUTPUT AS #i01 : PRINT #i01, File02; : CLOSE #i01
                File02 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 02) FOR OUTPUT AS #i01 : PRINT #i01, File03; : CLOSE #i01
                File03 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 03) FOR OUTPUT AS #i01 : PRINT #i01, File04; : CLOSE #i01
                File04 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 04) FOR OUTPUT AS #i01 : PRINT #i01, File05; : CLOSE #i01
                File05 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 05) FOR OUTPUT AS #i01 : PRINT #i01, File06; : CLOSE #i01
                File06 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 06) FOR OUTPUT AS #i01 : PRINT #i01, File07; : CLOSE #i01
                File07 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 07) FOR OUTPUT AS #i01 : PRINT #i01, File08; : CLOSE #i01
                File08 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 08) FOR OUTPUT AS #i01 : PRINT #i01, File09; : CLOSE #i01
                File09 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 09) FOR OUTPUT AS #i01 : PRINT #i01, File10; : CLOSE #i01
                File10 = ""
      
            CASE 20
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 00) FOR OUTPUT AS #i01 : PRINT #i01, File01; : CLOSE #i01
                File01 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 01) FOR OUTPUT AS #i01 : PRINT #i01, File02; : CLOSE #i01
                File02 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 02) FOR OUTPUT AS #i01 : PRINT #i01, File03; : CLOSE #i01
                File03 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 03) FOR OUTPUT AS #i01 : PRINT #i01, File04; : CLOSE #i01
                File04 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 04) FOR OUTPUT AS #i01 : PRINT #i01, File05; : CLOSE #i01
                File05 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 05) FOR OUTPUT AS #i01 : PRINT #i01, File06; : CLOSE #i01
                File06 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 06) FOR OUTPUT AS #i01 : PRINT #i01, File07; : CLOSE #i01
                File07 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 07) FOR OUTPUT AS #i01 : PRINT #i01, File08; : CLOSE #i01
                File08 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 08) FOR OUTPUT AS #i01 : PRINT #i01, File09; : CLOSE #i01
                File09 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 09) FOR OUTPUT AS #i01 : PRINT #i01, File10; : CLOSE #i01
                File10 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 10) FOR OUTPUT AS #i01 : PRINT #i01, File11; : CLOSE #i01
                File11 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 11) FOR OUTPUT AS #i01 : PRINT #i01, File12; : CLOSE #i01
                File12 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 12) FOR OUTPUT AS #i01 : PRINT #i01, File13; : CLOSE #i01
                File13 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 13) FOR OUTPUT AS #i01 : PRINT #i01, File14; : CLOSE #i01
                File14 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 14) FOR OUTPUT AS #i01 : PRINT #i01, File15; : CLOSE #i01
                File15 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 15) FOR OUTPUT AS #i01 : PRINT #i01, File16; : CLOSE #i01
                File16 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 16) FOR OUTPUT AS #i01 : PRINT #i01, File17; : CLOSE #i01
                File17 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 17) FOR OUTPUT AS #i01 : PRINT #i01, File18; : CLOSE #i01
                File18 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 18) FOR OUTPUT AS #i01 : PRINT #i01, File19; : CLOSE #i01
                File19 = ""
      
                i01 = FREEFILE
                OPEN "threads_formatted\" + URLs(StartPT + 19) FOR OUTPUT AS #i01 : PRINT #i01, File20; : CLOSE #i01
                File20 = ""
        END SELECT
      
        QueryPerformanceCounter qStopSave
        qSaveAccum = qSaveAccum + (qStopSave - qStartSave)
      
      END SUB
      Last edited by Jim Fritts; 26 Aug 2020, 03:34 AM.

      Comment

      Working...
      X
      😀
      🥰
      🤢
      😎
      😡
      👍
      👎