Announcement

Collapse
No announcement yet.

Messagebox in separate thread

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

    Messagebox in separate thread

    In his thread on the source code forum http://www.powerbasic.com/support/pb...ad.php?t=41714
    Mel Bishop added the remark :

    My original purpose for playing with it was to bring up a MessageBox without stalling the program.
    ... Never did find an answer for that one.
    Well, just place the messagebox in a separate thread.
    Below you find an example that shows the general idea.

    Arie Verheul


    Code:
     
    #Break On
    #Include "win32api.inc"
     
     
    Function PBMain () As Long
     
        Dim MsgText  As Global Asciiz*60
        Dim Response As Global Long
     
        Local hThread, ThreadVar As Dword
        Local I,J,K,L As Dword
     
        MsgText = "Just say so if you want to stop when this set is finished"
     
     
        Do
     
        For J = 2 To 9
            For I = 1 To 10
                K = I * J
                Locate I + 2, 5
                Print Using$("## x ## = ###",I,J,K)
                Sleep 100
            Next
            Sleep 1000
            Cls
        Next
     
        Incr L
     
        If L = 1 Then Thread Create Message (ThreadVar) To hThread
     
        Loop Until Response = 6
     
    End Function
     
     
    Thread Function Message (ByVal ThreadVar As Dword)  ' ThreadVar is a dummy variable
     
        MessageBox 0, MsgText, "Test Message Box" , 4 To Response
      
    End Function

    #2
    Much obligated for the example, Arie. Works like a champ.

    It never entered my head to go that route.
    There are no atheists in a fox hole or the morning of a math test.
    If my flag offends you, I'll help you pack.

    Comment


      #3
      Not sure nowadays with the PB compilers but i still keep using critical sections.
      Is there a shortroute in PB for this?

      Imo Response must be address aligned and when obtained blocked by a CS?

      I heard something about thread variables??
      hellobasic

      Comment


        #4
        >Is there a shortroute in PB for this?

        Come on, Edwin. There is no elevator.....

        FWIW, All PowerBASIC intrinsic functions are thread-safe. I have no idea HOW they do it (Critical sections? Thread Local Storage? Thread-indexed tables in the runtime?)

        Of course, I do not care about the HOW, I only care about the WHAT.

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

        Comment


          #5
          So?
          What would you do with the Response variable?
          hellobasic

          Comment


            #6
            >So? What would you do with the Response variable?

            You mean in real life? (in demo life, I'd hold my nose and loop on it).

            Well, in Real Life I'd use this....
            Terminate Worker Threads Using Windows Events (and Using Thread Local Storage) Demo Dec 23 2005

            .. with my thread handle as the 'abort' object. When MessageBox() is dismissed, the thread function ends, signalling the thread object.

            No muss, no fuss, no bother.

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

            Comment


              #7
              That seems way to complex for this single var issue imo.
              hellobasic

              Comment


                #8
                >That seems way to complex for this single var issue imo.

                Perhaps; but just think of all the style points!
                Michael Mattias
                Tal Systems (retired)
                Port Washington WI USA
                [email protected]
                http://www.talsystems.com

                Comment


                  #9
                  Was this a PBCC topic? I didn't recognize all of the function in the example.

                  Comment


                    #10
                    Yes Edwin, unfortunately all Michaels thread examples get low style marks as they are unneccasrily complicated. To answer your specific question the response variable can be returned to the GUI in a Windows message i.e in DDT you would pass CBHNDL to the thread at startup (either by itself or in a UDT if other info need to be passed) as say HDlg. The thread would send the response variable back to the GUI with DIALOG SEND HDlg, %User + something, Response in wParam&, 0 and then end.
                    Most thread issues can be simply handled with Windows messages by the thread reading a control on the GUI as long as you don't start the thread and follow it with a Wait for Single Object. Globals of course make it very simple if you are only looking for a True/False as long read are Atomic so no synchronisation is needed.

                    Comment


                      #11
                      Globals of course make it very simple if you are only looking for a True/False as long read are Atomic so no synchronisation is needed
                      AND.... you are willing to spend the clocks to read and test it ....
                      Michael Mattias
                      Tal Systems (retired)
                      Port Washington WI USA
                      [email protected]
                      http://www.talsystems.com

                      Comment


                        #12
                        Originally posted by Michael Mattias View Post
                        AND.... you are willing to spend the clocks to read and test it ....
                        That statement makes no sense, it is much faster to read a single Global long than to check an event.

                        Comment


                          #13
                          The WaitForSingleObject function checks the current state of the specified object. If the object's state is nonsignaled, the calling thread enters the wait state. It uses no processor time while waiting for the object state to become signaled or the time-out interval to elapse [italics mine]
                          (WFSO is the waiting mechanism employed in linked demo)

                          I'm no clocks counter guy, but I think reading and testing a variable takes more than zero time.

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

                          Comment


                            #14
                            Let's forget about speed issues for a while.
                            My main concern is that multiple threads are able to read (and even during write) the same (global) variable.
                            This is dangerous and only one thread should access a specific variable at a time.
                            Unless.., PB has some internal stuff which no longer requires this.
                            That would make my day!

                            Note that a few years ago i had a similar issue which GPF'd on a specific CPU type only.
                            I implemented a CS and never heard about it again.
                            You just have to avoid multiple read and writes on the same address.
                            hellobasic

                            Comment


                              #15
                              >unless.. PB has some internal stuff which no longer requires this

                              No, the 'thread safeness-and-integrity' of STATIC and GLOBAL variables has always been and remains the responsibility of the programmer.

                              >You just have to avoid multiple read and writes on the same address

                              If you need 'atomic' updates of a GLOBAL variable, for integers you can use the Interlockedxxxxxx WinAPI functions, for others you have to use a synchronization object such as the Critical Section.

                              Since the CPU can only do one thing at a time, I suspect your problem occurred during some non-atomic operation which changes an address....eg assignment of a new value to a dynamic string... there could be points in time during that operation when the "address" in your variable is not valid. (eg the STRPTR value of a dynamic string changes during assignment)
                              Michael Mattias
                              Tal Systems (retired)
                              Port Washington WI USA
                              [email protected]
                              http://www.talsystems.com

                              Comment


                                #16
                                Edwin,

                                Have you looked at PB's THREADED variables?

                                Thread variables have a distinct advantage over global variables as they avoid the need to use synchronization techniques (such as a Critical Section object or Mutex) when referencing (reading or writing) from two or more threads at the same time. In addition, all allocation and deallocation of THREADED memory is handled automatically by PowerBASIC without any need for intervention by the programmer. However, by their nature, thread variables impose a slight, yet measurable, performance penalty as compared to other variable types.
                                Rgds, Dave

                                Comment


                                  #17
                                  No globals using pointers (see Create Thread in docs)

                                  Also demonstrates using WaitForSingleObject or polling

                                  Code:
                                  #INCLUDE "win32api.inc"
                                  %WFSO = 0  '1 =WAITFORSINGLEOBJECT, 0=Polling
                                  TYPE MyUDT
                                    s AS STRING * 80
                                  END TYPE
                                  FUNCTION PBMAIN () AS LONG
                                    DIM x AS MyUDT, hThread???, counter AS LONG
                                    IF %WFSO THEN
                                      x.s = "WAITFORSINGLEOBJECT"
                                    ELSE
                                      x.s = "Polling"
                                    END IF
                                    THREAD CREATE MessageBoxThread(VARPTR(x)) TO hThread???
                                    SLEEP 50 'give thread time to allocate (required)
                                    IF %WFSO = 0 THEN
                                      DO UNTIL THREADCOUNT = 1
                                        BEEP
                                        SLEEP 1000
                                      LOOP
                                    ELSE
                                      WaitForSingleObject hThread,%INFINITE
                                    END IF
                                    THREAD CLOSE hThread TO hThread
                                  END FUNCTION
                                  THREAD FUNCTION MessageBoxThread(BYVAL y AS DWORD) AS DWORD
                                    DIM x AS MyUDT POINTER
                                    x = y
                                    ? @x.s
                                  END FUNCTION
                                  Last edited by Mike Doty; 17 Oct 2009, 12:50 PM. Reason: Compact

                                  Comment


                                    #18
                                    Ah yes, this has been mentioned to me earlier and should have looked it up.

                                    >THREADED t1 AS LONG
                                    That may be a good thing to have here

                                    Thanks!
                                    hellobasic

                                    Comment


                                      #19
                                      Oops, this is the tlsalloc stuff..
                                      Not useful i guess for a global signalling or other shared variable.
                                      hellobasic

                                      Comment


                                        #20
                                        I think we have got a little off the subject here. The OP asked about MessageBoxes that did not disrupt processing, an answer was given of use a thread. Edwin then asked how would you return the response, simple DIALOG SEND.
                                        The subject has now gone on to IMHO show some serious misconceptions. First Dave at least as how I read the description, Threaded Variables are local to a thread so can't be used for passing information between threads.
                                        We have Michael the professor who thinks WFSO takes zero time. Totally wrong, it gives up all its time slices till the condition is met and that could be milliseconds to hours and of course every time cycle it is given requires numererous clock cycles to check the condition DUH.
                                        Of course any inter thread variable (or to the main program) requires some form of synchronisation unless it is a global long being used as a true false flag and true is anything other than zero. This is because a long read is truely atomic without any need for synchronisation i.e. even if it is half written it is read as true.
                                        All the examples I have seen ignore the basic method of Windows for synchonisation which is messages. If you want a thread to notify it has finished (and its results are somewhere) Post it in a message. If you want the thread to stall waiting a response Send it in a message, its in most cases that easy.
                                        If on the other hand you set up a WFSO immediately creating the thread then you cause problems with the main program that creates the threads, then things like telling the thread to abort become very messy pieces of code.

                                        Comment

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