Announcement

Collapse
No announcement yet.

Process in background (called from VB)

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

  • Process in background (called from VB)

    What would be a good way to pass data back to Visual Basic?
    No WAITFORSINGLEOBJECT because VB would have to wait which defeats the purpose of processing in the background.

    The code below works great passing information from VB to PB and processing everything in the background so the VB program is always responsive.

    Code:
    #COMPILE DLL "background.dll"
     
    DECLARE SUB BACKGROUND LIB "background.dll" (s$)
     
    GLOBAL gs AS STRING
     
    SUB Background(s AS STRING) EXPORT
     
      'Do NOT SLEEP or WAITFORSINGLEOBJECT here or caller will wait
      LOCAL hThread, x AS DWORD
      gs=s
      THREAD CREATE BackGroundThread(x) TO hThread
      SLEEP 50
      THREAD CLOSE hThread TO hThread
     
    END SUB
     
    THREAD FUNCTION BackGroundThread(BYVAL dummy AS DWORD) AS DWORD
     
      SLEEP 5000  'simulate processing
      ? gs + " done processing at " + TIME$  'pass data back here?
     
    END FUNCTION
    Post #10 below is a tested working example of using threading with critical section protection
    Last edited by Mike Doty; 30 May 2009, 09:29 AM.
    The world is full of apathy, but who cares?

  • #2
    Post or send a message.

    Write a file to a monitored folder.

    Write to a monitored pipe or mailslot.

    Signal a named event.

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

    Comment


    • #3
      Good answers, thankyou, and PrivateClipboard.
      The world is full of apathy, but who cares?

      Comment


      • #4
        I take it creating additional threads of execution with VB is either impossible or rife with restrictions?
        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          No.
          I have not had a problem using threads written in PB callled from VB.
          At first I was thrown off by not just letting the function calling the THREAD CREATE just run to completion.
          When threaded functions are called in a DLL they are not ended like when called from PBMAIN (the first thread.)
          The threads all end if VB6 ends just like they would if PBMAIN had issued the Thread Create.
          In other words, threads with VB are simple and reliable using PowerBASIC.

          Note:
          If working in the VB environment and the VB6 program ends while threads are still running then
          those threads should be terminated by ending the VB6 environment or the environment will be crashed.
          There might be a way to end them when the form unloads without taking down the environment.
          Compiled VB6 programs do not have this problem.
          Calling ExitProcess when the VB program unloads from within the environment will also take down the environment.
          Last edited by Mike Doty; 29 May 2009, 04:46 PM.
          The world is full of apathy, but who cares?

          Comment


          • #6
            No, I meant VB must make it difficult to create additional threads of execution WITHIN VB.

            Otherwise you would not be asking because you could just...

            Code:
            ' MY_VB_PROGRAM.BAS 
            
            ....  
             hThread = CreateThread ( lpAttributes, Stacksize, _
                 CODEPTR (VB_THREAD_FUNCTION), _
                param, _
                CreateFlags,_
                ThreadID)
            
                 yadda, yadda, yadda 
            
            ...
            ...
            
            FUNCTION VB_THREAD_FUNCTION (param) 
            
              CALL MyPbFunctionInMyDLL (Param) 
            
            END FUNCTION
            .. or did you not think that possible?

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

            Comment


            • #7
              I was not asking how to create threads from within VB.
              I was asking how to return information.
              I posted a working program above on how to do it.
              To create a thread within VB can be done and is an option, thank you for bringing it up.

              I see your point, but I want to do threading using PB.
              Last edited by Mike Doty; 29 May 2009, 07:01 PM.
              The world is full of apathy, but who cares?

              Comment


              • #8
                Hi Mike,

                The simplest way I can think of is to have a hidden textbox on a form in VB and pass the handle to it to the PB DLL, then have PB send a WM_SETTEXT to it to pass whatever information you need.

                On the VB end you just respond to the Change event for the textbox (and parse the text you sent if need be).

                I doubt you need it, but I can put together a really simple example if you want.

                Regards,

                Pete.

                Comment


                • #9
                  Mike
                  Why not just put a callback function in the VB code.
                  John

                  Comment


                  • #10
                    CALLBACK in VB. I'll have to study to do that. Thank you!

                    Code:
                    #COMPILE DLL "background.dll"
                    #INCLUDE "win32api.inc"
                    DECLARE SUB BACKGROUND LIB "background.dll"(sQuestion AS STRING, sAnswer AS STRING)
                    GLOBAL gCS AS CRITICAL_SECTION
                    GLOBAL g_Question$, g_Answer$
                    '--------------------------------------------------------------
                    SUB Background(sQuestion AS STRING, sAnswer AS STRING) EXPORT
                      'NO SLEEP or WAIT in this function (this in first thrread)
                      LOCAL hThread, Result AS DWORD
                      EnterCritical
                      g_Question = sQuestion
                      LeaveCritical
                      THREAD CREATE BackGroundThread(hThread) TO hThread
                      IF hThread = 0 THEN ? "Unable to create thread":EXIT SUB
                      DO
                        DIALOG DOEVENTS 0                'allow others time
                        THREAD STATUS hThread TO Result  'get thread status
                      LOOP WHILE Result = &H103          'loop while running
                      THREAD CLOSE hThread TO Result     'close thread handle
                      IF Result = 0 THEN ? "Error closing thread"
                      EnterCritical
                      sAnswer = g_Answer                 'return answer from background thread
                      LeaveCritical
                    END SUB
                    '--------------------------------------------------------------
                    THREAD FUNCTION BackGroundThread(BYVAL dummy AS DWORD) AS DWORD
                      LOCAL sQuestion AS STRING
                      LOCAL sAnswer   AS STRING
                      EnterCritical
                      sQuestion = g_Question
                      LeaveCritical
                      'dim simulate as long:for simulate = 1 to 5:SLEEP 1000:BEEP:NEXT 'simulate working
                    
                      SELECT CASE sQuestion
                        CASE ""
                          sAnswer = "No question"
                        CASE ELSE
                          sAnswer = TIME$ + " some answer"
                       END SELECT
                      EnterCritical
                      g_Answer = sAnswer
                      LeaveCritical
                    END FUNCTION
                    '--------------------------------------------------------------
                    FUNCTION GetThreadCount EXPORT AS LONG 'VB uses to not end until threadcount = 1
                      FUNCTION = THREADCOUNT
                    END FUNCTION
                    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                    SUB EnterCritical
                       EnterCriticalSection gCS
                    END SUB
                    '--------------------------------------------------------------
                    SUB LeaveCritical
                       LeaveCriticalSection gCS
                    END SUB
                    
                    FUNCTION LIBMAIN(BYVAL hInstance AS DWORD, _
                                     BYVAL lReason AS LONG,    _
                                     BYVAL lReserved AS LONG) AS LONG
                      SELECT CASE AS LONG lReason
                        CASE %DLL_PROCESS_ATTACH
                          REM ? "DLL attached"
                          InitializeCriticalSection gCS
                          LIBMAIN = 1
                          EXIT FUNCTION
                        CASE %DLL_PROCESS_DETACH
                          REM ? "This DLL is about to be unloaded
                           DeleteCriticalSection gCS
                              EXIT FUNCTION
                        CASE %DLL_THREAD_ATTACH
                          ' A [New] thread is starting (see THREADID)
                          EXIT FUNCTION
                        CASE %DLL_THREAD_DETACH
                          ' This thread is closing (see THREADID)
                          EXIT FUNCTION
                      END SELECT
                      LIBMAIN = 0 ' Indicate failure to initialize the DLL!
                    END FUNCTION
                    Last edited by Mike Doty; 30 May 2009, 09:58 AM. Reason: Posting truncated and reduced dialog doevents 0
                    The world is full of apathy, but who cares?

                    Comment


                    • #11
                      Mike
                      Fairly simple, only two special requirements, the sub or function must be in a module not a form and must be public. No special limits on the number or type or number of fields passed back other than the usual ones of passing data to and from VB and a DLL. a simple outine as follows
                      Public Function MyCallback(variable list as usual) As Long
                      pass address to a DLL exported function or sub, say CAddress(Addr as DWORD) as LONG as follows in VB
                      Return& = Caddress(AddressOf MyCallback)
                      Note AddressOf is key word similar to CODEPTR

                      Comment


                      • #12
                        I'll give that a shot!
                        Need to get some sleep. Worked on this all night.
                        By the way, the code I posted always works compiled and has never crashed the environment
                        No threadcount problem.
                        The world is full of apathy, but who cares?

                        Comment


                        • #13
                          Oooh, oooh, a callback. Why didn't I think of that? That's a good idea. I like it.

                          From callback procedure, post a private message to your primary GUI window and there you go. (I assume that's possible; I have not touched VB since VB3. BTW, I do have a VB3 Pro in the box with license card and all the manuals on real paper! Maybe it's fantastically valuable by now.)
                          Michael Mattias
                          Tal Systems (retired)
                          Port Washington WI USA
                          [email protected]
                          http://www.talsystems.com

                          Comment


                          • #14
                            Michael
                            You have been using SDK too long , no need for messages, VB will let you update values, controls and call form event procedures directly from the callback function (so long as you remember that at some time you must return to the DLL for it to continue its work).
                            John

                            Comment


                            • #15
                              I was thinking you would want to quickly allow the thread function to terminate, so in your callback you would do something that did not take very long... like posting a message.

                              Besides, you have to remember the callback procedure is executing in the context of the additional thread of execution, and depending on your code you may have data integrity issues with which you must be concerned.

                              By using the callback function ONLY to post a message, you A) exit quicky, B) ensure you don't have any reentrancy issues and C) ensure that all the "thread function has completed" activities are performed only when any concurrent GUI activities (e.g, the notification message currently being processed in the primary TOE) have been completely processed.

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

                              Comment


                              • #16
                                VB6 does not like the re-entry of threads, the callback part will fail.
                                A message is the most ideal imo.

                                You could also do something about the non-responsive gui but that subject.. no one takes my hint on that..
                                Tried a few times..
                                hellobasic

                                Comment


                                • #17
                                  Edwin, what hint?
                                  Message is most ideal, I'll work on that.
                                  The code I posted #10 enables a VB gui that is responsive and has critical sections in the DLL.
                                  I'm trying to do all threading in PB to eliminate re-entry issues, etc.

                                  This appears to work. Critical sections are hopefully all in the right place.
                                  DIALOG DOEVENTS 0 seemed to make VB gui responsiive.


                                  I've curious if EnterCriticalSection should also be callled before creating the thread?


                                  Code:
                                  SUB Background(sQuestion AS STRING, sAnswer AS STRING) EXPORT
                                   
                                    LOCAL hThread, Result AS DWORD
                                    EnterCritical
                                    g_Question = sQuestion
                                    LeaveCritical
                                    THREAD CREATE BackGroundThread(hThread) TO hThread
                                    IF hThread = 0 THEN ? "Unable to create thread":EXIT SUB
                                    DO
                                      DIALOG DOEVENTS 0                'allow others time
                                      THREAD STATUS hThread TO Result  'get thread status
                                    LOOP WHILE Result = &H103          'loop while running
                                    THREAD CLOSE hThread TO Result     'close thread handle
                                    IF Result = 0 THEN ? "Error closing thread"
                                    EnterCritical
                                    sAnswer = g_Answer                 'return answer from background thread
                                    LeaveCritical
                                  END SUB
                                  Last edited by Mike Doty; 30 May 2009, 10:53 AM.
                                  The world is full of apathy, but who cares?

                                  Comment


                                  • #18
                                    Hint.. oh a while ago, threads have been discussed recently.
                                    hellobasic

                                    Comment


                                    • #19
                                      I'[m] curious if EnterCriticalSection should also be callled before creating the thread?
                                      You don't even need a critical section here beccause it is not possible for you to get to the statement where you assign sAnswer = g_answer until the thread function has completed, meaning the value cannot possibly change.

                                      Which brings us to how you know the thread function has completed....
                                      Code:
                                      DO
                                          DIALOG DOEVENTS 0                'allow others time
                                          THREAD STATUS hThread TO Result  'get thread status
                                      LOOP WHILE Result = &H103          'loop while running
                                      I don't know what DIALOG DOEVENTS does (and unless I am mistaken its implementation has changed several times over the past couple of releases of PB/WIN), but this is assuming whatever it does is sufficient for and consistent with whatever a VB program uses to retrieve and dispatch messages from its message queue.

                                      If it works, fine, but you need to be aware you are operating in uncharted waters here.

                                      Can anyone give me a straight answer about creating additional TOEs using the CreateThread() API in VB? I can't see how that could screw up the VB program as long as the thread function does not try doing anything with any of the objects managed by the primary TOE of the VB program.

                                      That is, if the thread function does not even think about doing anything to cause a re-entrancy, should it not work just fine?




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

                                      Comment


                                      • #20
                                        Originally posted by Edwin Knoppert View Post
                                        VB6 does not like the re-entry of threads, the callback part will fail.
                                        A message is the most ideal imo.

                                        You could also do something about the non-responsive gui but that subject.. no one takes my hint on that..
                                        Tried a few times..
                                        Not really Edwin. Yes VB6 is a single threaded apartment model (or described something like that) so it is very difficult but not impossible to create threads in VB6, however you can create threads in the PB DLL, I assume I didn't describe the situation correctly.
                                        VB calls a PB DLL with data, The PB DLL spawns threads to process that data. If a thread completes its work it reports that data back to the main DLL thread which passes the results to the VB program via the callback. As I said previously the callback function must return to the DLL before it can do any more work (should I have said before it calls the callback again), thus all VB remains in the single thread it knows exists and is totally unaware that other processing might have taken place in multiple threads or even on other computers.

                                        Comment

                                        Working...
                                        X