Announcement

Collapse
No announcement yet.

MultiThread Question

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

  • MultiThread Question

    Hello

    In a program with many worker threads running, one Main thread in higher
    priority receiving messages from worker threads(Sendmessage to Main thread).
    Code:
    'Is this a better procedure
    Do
      WaitMessage
      Dialog Doevents               'User Input
      if quitflag then exit do
    Loop
    'Than this
    Do
      x=PeekMessage(msg, hDlg, 0, 0, 0)     'No Remove
      if x then
            Dialog Doevents
      else
            Sleep w           'w computed based on number of worker threads
      end if
      if quitflag then exit do
    Loop
    Did not know much about WaitMessage.

    Thanks

  • #2
    >Main thread in higher
    >priority receiving messages from worker threads(Sendmessage to Main thread).

    Messages are not sent to threads. Messages are sent to windows.

    You do not need a message loop (DIALOG DOEVENTS) in any thread except threads which create windows (DIALOG NEW/SHOW); you will generallly only create windows in one (1) thread of your application... your extra threads of execution will be 'background' or "batch" tasks started based on what the user does.

    Here is a demo you should review:
    GUI + Worker Thread + Abort Demo 11-24-07

    I think it is a terrific demo of the Right Way to handle a user interface plus worker threads. However, I am not exactly a neutral party.

    MCM
    Michael Mattias
    Tal Systems Inc. (retired)
    Racine WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      But to answer yoiur question directly, if you are using DDT to create your windows, just use the DDT message loop in your primary Thread of Execution (the one in which your create your windows) . Don't insert WaitMessage... let the compiler generate the optimal code for message processing. I dare suggest the folks in Florida have given this a bit more thought than have you.

      MCM
      Michael Mattias
      Tal Systems Inc. (retired)
      Racine WI USA
      [email protected]
      http://www.talsystems.com

      Comment


      • #4
        Sorry I forgot to mention, main thread is a modeless window.
        I think the reason for modeless is because it is running in higher priority.
        Code:
            DIALOG SHOW MODELESS hDlg, Call xDialog TO x
            Do
               WaitMessage
               DIALOG DOEVENTS
               IF quitflag THEN EXIT DO
            LOOP
        '***************************************************************
        FUNCTION thread_run(BYVAL i AS LONG) AS LONG
        '***************************************************************
            DO
                'Code here
                'Code here
                SendMessage hDlg, %THREAD_SUSPEND, 0, i
            LOOP
        END FUNCTION
        Worker threads sendmessage to Main thread Window.

        Thank you

        Comment


        • #5
          >I think the reason for modeless is because it is running in higher priority

          Modal/Modeless is programmer decision and is not tied to thread priority at all.

          MCM
          Michael Mattias
          Tal Systems Inc. (retired)
          Racine WI USA
          [email protected]
          http://www.talsystems.com

          Comment


          • #6
            Originally posted by Michael Mattias;319526Here is a demo you should review:
            [url=http://www.powerbasic.com/support/pbforums/showthread.php?t=35619
            GUI + Worker Thread + Abort Demo 11-24-07[/url]

            I think it is a terrific demo of the Right Way to handle a user interface plus worker threads. However, I am not exactly a neutral party.

            MCM
            MCM
            Yes it is a good example but I think it is overly complex for what it is trying to do (particularly with a couple of GLOBALS).
            All the steps you show can be done with a few simple Windows messages, no Mutexes and no WaitForSingleObject. It can be all done with a few User messages which removes the problem of the DDT main being stalled while waiting or horrendously slow if polling. To take your example.
            The user types in the file name/details and clicks %ID_Start the first action for this is to make the input textbox read only, Second it does Thread Create, then Thread Close.
            The thread can then get the details with a simple Control Get Text as the Dialog is not stalled in a waitfor statement.
            The thread can then update the Dialog with simple Control Set Text or update a progress bar etc.
            Abort, well thats a simple matter of setting a flag in a Global Long which is checked by the thread whenever, no need for Mutex's etc as a simple long read is an Atomic instruction.
            Last instruction of the thread before END FUNCTION is Dialog Post a user message indicating thread ended and the whole process can be run again.
            Take a more complex situation where you might wish to keep the thread alive but give it new data. Again easy but this time the thread uses Dialog Send a user message saying give me new info. The thread is then suspended until the Dialog returns from that message, simple synchronisation.
            John

            Comment


            • #7
              which removes the problem of the DDT main being stalled .......as the Dialog is not stalled in a waitfor statement ... can be done with a few simple Windows messages, no Mutexes ...
              There is no mutex object used in the linked demo, so I'm not sure you have reviewed the correct example.

              However, in the (correct) demo the primary thread is suspended only when the worker thread of execution is first launched, and suspended only until the thread function has copied its parameters to a LOCAL variable, safe from change by anything occurring in another TOE. It is never suspended after that.

              Take a more complex situation where you might wish to keep the thread alive but give it new data.
              "Complex" is something I try to avoid in my demos. This is by design.

              However, even though 'complex' is a little off topic for this [forum] thread, externally changing the data in an executing TOE is IMO totally silly. A well-designed application would simply launch a fresh TOE using the new parameters.

              Perhaps everyone's interests would be best served by you posting demos of your suggested techniques. Why don't you post that (those?) as replies to my demo; that will make it easy for users to 'pick and choose.'

              MCM
              Michael Mattias
              Tal Systems Inc. (retired)
              Racine WI USA
              [email protected]
              http://www.talsystems.com

              Comment


              • #8
                MCM
                Sorry didn't mean to imply your demo used a mutex it uses a more complicated WaitForSingle for the abort when simply setting a global long flag would do the job.
                However, in the (correct) demo the primary thread is suspended only when the worker thread of execution is first launched, and suspended only until the thread function has copied its parameters to a LOCAL variable, safe from change by anything occurring in another TOE. It is never suspended after that.
                Not quite as the comments in your demo complaining about documentation note you were not able to get the filespecs with a simple Control Get Text, my suggestions solve that.
                However, even though 'complex' is a little off topic for this [forum] thread, externally changing the data in an executing TOE is IMO totally silly. A well-designed application would simply launch a fresh TOE using the new parameters.
                In most cases I would agree, was just expanding the options.

                Comment


                • #9
                  comments in your demo complaining about documentation note you were not able to get the filespecs with a simple Control Get Text,
                  This I will call a 'meaningful omission' in the documentation for CONTROL GET TEXT.

                  Besides, I got the text, didn't I? And subsequent users know now that CONTROL GET TEXT is NOT going to do the job for them?

                  The "complexity" in that demo is almost one hundred percent the result of designing it to support an "abort" event.

                  While polling a GLOBAL variable would "work", that option is not available if the thread function is located in a different code module. The demo as written would work just fine were the workher thread function lifted out and '#COMPILEd DLL' (You'd need a stub/wrapper function in the main module to serve as the object of the THREAD CREATE statement, since PB does not support THREAD CREATE with anything but the "user name" of the thread function. Eg, no such thing as 'THREAD CREATE DWORD functionaddress' although that would be pretty cool)



                  See also:
                  Terminate Worker Threads Using Windows Events (and Using Thread Local Storage) Demo Dec 23 2005
                  Last edited by Michael Mattias; 24 Jul 2009, 01:18 PM.
                  Michael Mattias
                  Tal Systems Inc. (retired)
                  Racine WI USA
                  [email protected]
                  http://www.talsystems.com

                  Comment


                  • #10
                    Originally posted by Michael Mattias View Post
                    This I will call a 'meaningful omission' in the documentation for CONTROL GET TEXT.

                    Besides, I got the text, didn't I? And subsequent users know now that CONTROL GET TEXT is NOT going to do the job for them?
                    but it does work if you don't complicate the process.

                    The "complexity" in that demo is almost one hundred percent the result of designing it to support an "abort" event.

                    While polling a GLOBAL variable would "work", that option is not available if the thread function is located in a different code module. The demo as written would work just fine were the workher thread function lifted out and '#COMPILEd DLL' (You'd need a stub/wrapper function in the main module to serve as the object of the THREAD CREATE statement, since PB does not support THREAD CREATE with anything but the "user name" of the thread function. Eg, no such thing as 'THREAD CREATE DWORD functionaddress' although that would be pretty cool)
                    Sorry don't understand, Globals work perfectly across INC files if that is what you mean by module. If you mean DLL's then the Global of that DLL is simply set with another exported function.
                    More on
                    externally changing the data in an executing TOE is IMO totally silly. A well-designed application would simply launch a fresh TOE using the new parameters
                    Actually I have a major program that at start up starts 3 more threads, none of which ends until the program ends. Without going into details the main program responds to a KeyDown message sent from a VB DLL. If my program wants to use the information available from the VB DLL it passes the information to a FIFO queue of a thread to process. That thread can then request more information from two other threads (different internet sources) adding it to their FIFO work queues which don't try for out of time or redundent info. Both of these threads when getting info add it back to the the queue of the info processing thread.
                    I haven't been able to work out a way that each of peices of data should be able to be handled by use once threads and be able to review and optimise their work queues.
                    I know you could tell me a way . Of course they rely on mutexes not messages.
                    John
                    Last edited by John Petty; 24 Jul 2009, 02:09 PM.

                    Comment


                    • #11
                      > That thread can then request more information from two other threads...

                      "Threads" [of execution] do not maintain information. "Module" means "executable program file, either DLL or EXE."

                      As far as handling a FIFO queue.. Ye Olde Anonymouse Pipe Demo seems fairly handy..

                      Anonymous Pipe as Job Queue Demo 10-29-03

                      ..but what may be handier is the "limit number of active threads using a semaphore" demo I have promised myself I will clean up and post this weekend. (It works great, but right now it's PB/CC only with output to the console. I want to add an 'activity' screen so both PB/CC and PB/WIN users can "plug and play" the same source code. It will also be a heck of lot easier to follow what's happening than trying to read the screen as it scrolls by)

                      In this case, you could have a pipe server thread function accepting requests, and waiting for the first available "slot" of the "N" maximum simultaneous worker threads allowed. i.e, if you want to limit active wokder threads the, say, five, and have Windows manage the necessary 'suspend and resume' a semaphore object will be just what the doctor ordered for you.

                      My demo would not serve this purpose, but in pseudo-code...

                      Code:
                      FUNCTION MAin() 
                      
                          DO 
                               getInput 
                               Write request to pipe. 
                          LOOP UNTIL NO-MORE-INPUT
                      
                      THREAD FUNCTION PipeReader  () 
                      
                       DO 
                            ReadPipe
                            WaitOnSemaphore  ( slot available) 
                            THREAD CREATE RealWork (app data from pipe)   
                       LOOP 
                      
                      THREAD FUNCTION RealWork (app data from Pipe) 
                          Yadda, yadda, yadda
                          ReleaseSemaphore hSemaphone    ' make a slot available 
                      END  FUNCTION
                      Something like that, anyway.

                      Optimization is different - it is perforce application specific. For me to comment on that I'd need documentation, source code and a purchase order.

                      MCM
                      Last edited by Michael Mattias; 24 Jul 2009, 03:18 PM.
                      Michael Mattias
                      Tal Systems Inc. (retired)
                      Racine WI USA
                      [email protected]
                      http://www.talsystems.com

                      Comment

                      Working...
                      X