Announcement

Collapse
No announcement yet.

Creating threads

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

  • Creating threads

    If I need to create a bunch of threads all using the same template, can I then use:

    Code:
    Thread Function MyThread (ByVal pCnt As Long) As Long
      Local VarA, VarB, VarC As Long
    End Function
    ​
    For Cnt = 1 to 10
      Thread Create MyThread(Cnt)  To hThread(Cnt)
    Next
    It creates 10 threads. But does it create separate code for every thread and it's variables?
    (or do they all share the same code?)
    Regards,
    Peter

  • #2
    Read the manual.
    THREAD CREATE statement
    ​There is a similar example.
    I hope that helps.

    Tasos Georgas.

    Comment


    • #3
      Ignoring threads for a moment. Any function you create with LOCAL/REGISTER (e.g. non-static or BYREF passed variables) will have their variables kept separate. As per THREAD CREATE --- As each thread is created, it is assigned its own "private" stack frame. Therefore, LOCAL and REGISTER variables are private to each thread, and are automatically "thread-safe".

      It is when you need to access/alter data outside the function itself you need to worry as the state of any external variable could be misinterpreted or incorrectly altered at the wrong time by any one of the threads that read or write without some sort of synchronization to ensure the external variables are in the expected state.

      For more info read up on THREAD CREATE, THREADSAFE, and THREADED
      <b>George W. Bleck</b>
      <img src='http://www.blecktech.com/myemail.gif'>

      Comment


      • #4
        For more info read up on....THREADSAFE, and ...
        Also note the THREADSAFE procedure directive uses a semaphore, and not a critical section, meaning it is not reentrant. That can be a "gotcha" depending on what you are really doing (your original post looks like a 'proof of concept' test function).
        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          I need upto 64 identical threads, so the above example is ideal for that. (don't want to write it 64 times... )
          I can't really see the difference between local and threaded vars; they both seem to do the same more or less in a thread function...
          Regards,
          Peter

          Comment


          • #6
            I can't really see the difference between local and threaded vars; they both seem to do the same more or less in a thread function..
            Can you see the difference between LOCAL and GLOBAL?

            THREADED variables are global to SUBs and FUNCTIONs being called from within a thread. From other threads separate copies of THREADED variables are "seen" by procedures called in each thread.
            Dale

            Comment


            • #7
              If you are trying to create a thread for each dialogic channel.... You might want to pass the dialogic channel id (long var,right) as the single long argument to the thread create.
              I can show you examples on wednesday when I get home.

              Comment


              • #8
                Click image for larger version  Name:	image.png Views:	1 Size:	37.6 KB ID:	819256
                Thread safe way to use a global string element for each thread and correctly wait for over 64-threads.
                Code:
                #INCLUDE ONCE "win32api.inc"
                '=============================================================
                FUNCTION PBMAIN AS LONG
                 LOCAL x,threads AS LONG
                 threads = 100
                 REDIM hThread(1 TO threads) AS LONG
                 REDIM gs(1 TO threads) AS GLOBAL STRING
                 FOR x = 1 TO threads
                  THREAD CREATE MyThread(x) TO hThread(x)
                 NEXT
                 ThreadWait hThread()
                 ? JOIN$(gs(),$TAB),%MB_SYSTEMMODAL,EXE.NAME$
                END FUNCTION
                '=============================================================
                THREAD FUNCTION MyThread(BYVAL threadnum AS LONG) AS LONG
                  gs(threadnum) = USING$("thread ###",threadnum)
                END FUNCTION
                '=============================================================
                FUNCTION ThreadWait(hThread() AS LONG) AS LONG
                 LOCAL ret,StartIndex,ThreadRemain,CurrentGroup,maxthread AS LONG
                 maxthread = ARRAYATTR(hThread(),4)  '11/13/21
                 StartIndex   = 1
                 ThreadRemain = MaxThread
                 DO
                  CurrentGroup = MIN(%MAXIMUM_WAIT_OBJECTS, ThreadRemain) 'process 64 then next batch
                  ret = WaitForMultipleObjects(CurrentGroup,BYVAL VARPTR(hThread(StartIndex)),%TRUE,%INFINITE)
                  StartIndex   = StartIndex   + %MAXIMUM_WAIT_OBJECTS
                  ThreadRemain = ThreadRemain - %MAXIMUM_WAIT_OBJECTS
                 LOOP WHILE ThreadRemain > 0
                 FOR StartIndex = 1 TO UBOUND(hThread) 'thread closes
                  THREAD CLOSE hThread(StartIndex) TO hThread(StartIndex)
                 NEXT
                END FUNCTION


                Last edited by Mike Doty; 3 Oct 2022, 06:24 PM.

                Comment


                • #9
                  Originally posted by Peter Lameijn View Post
                  I need upto 64 identical threads, so the above example is ideal for that. (don't want to write it 64 times... )
                  I can't really see the difference between local and threaded vars; they both seem to do the same more or less in a thread function...
                  The first part of Help is confusing: "Declare thread-local variables"
                  Ignore the word local
                  When you read the next part it is clearer:
                  "Threaded variables are global to every Sub, Function, Method, and Property but are not shared across threads."

                  Your Thread code can call functions.
                  Each thread can have it's own set of Threaded variables. Local variables in a thread are only accessible to code in the main thread function. They are not available to functions called within the thread unless they are passed as parameters. Threaded variables are available to any functions called by the main thread code. (They can have different values in different threads simultaneously. )

                  Comment


                  • #10
                    THREADED variables are global to SUBs and FUNCTIONs being called from within a thread. From other threads separate copies of THREADED variables are "seen" by procedures called in each thread.​
                    That's correct but hard to understand.

                    A THREADED variable is unique to the thread context in which it is executing.

                    If you call a procedure from a THREAD FUNCTION, it executes in the same thread context as the THREAD FUNCTION is currently executing.. except if you are calling a procedure which directly or indirectly call a window procedure, the window procedure always executes in the thread context owning that window.

                    Easiest way to deal with this is to pass as arguments any variables needed by the function you are calling from your THREAD FUNCTION.
                    Michael Mattias
                    Tal Systems (retired)
                    Port Washington WI USA
                    [email protected]
                    http://www.talsystems.com

                    Comment


                    • #11
                      This demonstrates threaded variables for accumulating subtotals in each thread.
                      Everything is logged into a unique global string element for each thread.
                      No passing variables, thread safe and easy to modify.
                      When working with client server programs threaded variables make things very easy.
                      Code:
                      THREADED tamount   AS CUX
                      THREADED tsubtotal AS CUX
                      
                      FUNCTION PBMAIN    AS LONG
                       LOCAL x,threads   AS LONG
                       threads = 3
                       REDIM hThread(1 TO threads) AS LONG
                       REDIM gs(1 TO threads) AS GLOBAL STRING
                       FOR x = 1 TO threads
                        THREAD CREATE MyThread(x) TO hThread(x)
                        THREAD CLOSE hThread(x) to hThread(x) 
                       NEXT
                       DO:SLEEP 250:LOOP UNTIL THREADCOUNT = 1
                       ? JOIN$(gs(),$CR),%MB_SYSTEMMODAL,EXE.NAME$
                      END FUNCTION
                      
                      SUB Invoice(ThreadNum AS LONG)
                       tamount = RND(100,200) 'random amount
                       tsubtotal+=tamount
                       gs(ThreadNum)+= USING$("Thread # Amount #  Subtotal # &",ThreadNum,tamount,tsubtotal,$CR)
                      END SUB
                      
                      THREAD FUNCTION MyThread(BYVAL ThreadNum AS LONG) AS LONG
                       LOCAL x AS LONG
                       FOR x = 1 TO RND(1,3) 'number of entries per thread
                        Invoice Threadnum
                       NEXT
                      END FUNCTION


                      Click image for larger version  Name:	image.png Views:	1 Size:	16.4 KB ID:	819305

                      Comment


                      • #12
                        It creates 10 threads. But does it create separate code for every thread and it's variables?
                        The answer to this question is "No." The code is created at compile time, one set only.

                        (Variables are created by executable statements actually executed by the code at run time.. but that's almost esoteric since "variable" is a compile-time concept. How your compiler treats variables is, well, basically the subject of this thread).
                        Michael Mattias
                        Tal Systems (retired)
                        Port Washington WI USA
                        [email protected]
                        http://www.talsystems.com

                        Comment

                        Working...
                        X