Announcement

Collapse

New Sub-Forum

In an effort to help make sure there are appropriate categories for topics of discussion that are happening, there is now a sub-forum for databases and database programming under Special Interest groups. Please direct questions, etc., about this topic to that sub-forum moving forward. Thank you.
See more
See less

pbthread.dll & pbtrdwd.dll <-- problem !

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

  • pbthread.dll & pbtrdwd.dll <-- problem !

    I was looking the tutorial on this link --> http://www.powerbasic.com/support/te...threading3.asp

    Consist on 2 dlls compiled with PowerBasic and that allow the multi-threads use from the Visual Basic 6. When i tried to compile the dlls with the PowrBasic 8.03 i got some errors on the sources, but at finally i found the changes required to compile.

    The pbthread.dll source i compiled is the follow code:

    $DEBUG ERROR ON
    $COMPILE DLL "PBThread.DLL"
    $INCLUDE "WIN32API.INC"

    ' CONSTANTS
    %MAX_SLEEP_TIME = 10000&
    %MIN_SLEEP_TIME = 1&
    %MT_NOTIFY = %WM_USER + 800

    ' TYPES
    Type ThreadPostInfo
    WindowHandle As Long
    CallbackAddress As DWORD
    End Type

    ' GLOBAL VARIABLES
    Global glngGeneralMutex As Long
    Global glngHInstance As Long

    ' FUNCTION/SUB DECLARATIONS
    Declare Function CreateCallbackWindow Lib "PBThrdWd.Dll" (lThreadID As Long) As Long
    DECLARE FUNCTION SleepForAWhile(BYVAL lpParam AS LONG) AS LONG
    DECLARE FUNCTION SpawnThreads (BYVAL CallbackFunctionAddress AS DWORD) AS LONG

    ' FUNCTION: LibMain
    FUNCTION LIBMAIN(BYVAL hInstance AS LONG, BYVAL fwdReason AS LONG, BYVAL lpvReserved AS LONG) EXPORT AS LONG
    On Error Resume Next
    Dim lngC As Long
    Dim lngRet As Long
    ' Store the instance handle for future reference.
    glngHInstance = hInstance
    Select Case fwdReason
    CASE %DLL_PROCESS_ATTACH
    ' Create the mutex.
    glngGeneralMutex = CreateMutex(BYVAL %NULL, %FALSE, BYVAL %NULL)
    LIBMAIN = 1
    Exit Function
    CASE %DLL_PROCESS_DETACH
    ' Close the mutex.
    CloseHandle glngGeneralMutex
    LIBMAIN = 1
    Exit Function
    CASE %DLL_THREAD_ATTACH
    LIBMAIN = 1
    Exit Function
    CASE %DLL_THREAD_DETACH
    ' If a window was created for this thread, destroy it.
    DIM ascWindowName AS ASCIIZ * 80
    Dim lngHWnd As Long
    ascWindowName = "MTExample" & Str$(GetCurrentThreadID())
    lngHWnd = FindWindow(BYVAL %NULL, ascWindowName)
    IF lngHWnd <> %NULL THEN
    SendMessage lngHWnd, %WM_DESTROY, %FALSE, %FALSE
    End If
    LIBMAIN = 1
    Exit Function
    End Select
    ' Any message which is not handled in the above SELECT CASE reaches
    ' this point and is unknown.
    End Function

    ' FUNCTION: SpawnThreads
    FUNCTION SpawnThreads ALIAS "SpawnThreads" (BYVAL CallbackFunctionAddress AS DWORD) EXPORT AS LONG
    ' This function creates a bunch of threads
    ' and each thread notifies the calling application
    ' when the work's done.
    '
    ' Returns TRUE on success, and FALSE on failure.
    On Error GoTo Error_SpawnThreads
    DIM ascWindowName AS ASCIIZ * 80
    Dim lngHeap As Long
    Dim lngHeapPtr As Long
    Dim lngHThreadResult As Long
    Dim lngHWnd As Long
    Dim lngIndex As Long
    Dim lngLength As Long
    Dim lngRet As Long
    Dim lngThreadID As Long
    Dim udtThreadInfo As ThreadPostInfo
    CALL WaitForSingleObject(glngGeneralMutex, %INFINITE)
    ' Assume a %FALSE for now.
    FUNCTION = %FALSE
    ' Create a window if necessary.
    lngThreadID = GetCurrentThreadID()
    ascWindowName = "MTExample" & Str$(lngThreadID)
    lngHWnd = FindWindow(BYVAL %NULL, ascWindowName)
    IF lngHWnd = %NULL THEN
    ' We need to create a window for this thread.
    lngHWnd = CreateCallbackWindow(lngThreadID)
    End If
    If lngHWnd <> 0 Then
    ' Allocate memory in the heap.
    lngLength = SIZEOF(udtThreadInfo)
    lngHeap = GetProcessHeap
    IF lngHeap <> %NULL THEN
    ' Create as many threads as needed.
    lngHeapPtr = HeapAlloc(lngHeap, 0, lngLength)
    If lngHeapPtr <> 0 Then
    udtThreadInfo.WindowHandle = lngHWnd
    udtThreadInfo.CallbackAddress = CallbackFunctionAddress
    ' We have success, copy the UDT into the heap.
    MoveMemory ByVal lngHeapPtr, ByVal VarPtr(udtThreadInfo), lngLength
    THREAD CREATE SleepForAWhile(lngHeapPtr) TO lngHThreadResult
    THREAD CLOSE lngHThreadResult TO lngRet
    End If
    'FUNCTION = %TRUE
    FUNCTION = lngHWnd
    End If
    End If
    Call ReleaseMutex(glngGeneralMutex)
    Exit Function
    Error_SpawnThreads:
    Call ReleaseMutex(glngGeneralMutex)
    End Function

    ' FUNCTION: SleepForAWhile
    Function SleepForAWhile(ByVal HeapPtr As Long) As Long
    ' This function will sleep somewhere between
    ' %MIN_SLEEP_TIME and %MAX_SLEEP_TIME seconds.
    ' Once it awakes, it'll post a completed message to a hidden window
    ' and terminate.
    On Error GoTo Error_SleepForAWhile
    Dim lngLength As Long
    Dim lngProcessHeap As Long
    Dim lngRet As Long
    Dim lngSleepTime As Long
    Dim udtThreadInfo As ThreadPostInfo
    lngLength = SIZEOF(udtThreadInfo)
    ' We have a pointer to a udt.
    ' Use CopyMemory and release the memory.
    MoveMemory ByVal VarPtr(udtThreadInfo), ByVal HeapPtr, lngLength
    ' Now release the memory!
    lngProcessHeap = GetProcessHeap
    lngRet = HeapFree(lngProcessHeap, 0, HeapPtr)
    lngSleepTime = RND(%MIN_SLEEP_TIME, %MAX_SLEEP_TIME)
    Call apiSLEEP(lngSleepTime)
    ' Now post a message to the correct window.
    ' The 3rd parameter is the function address.
    ' and the 4th signifies success.
    CALL SendMessage(udtThreadInfo.WindowHandle, %MT_NOTIFY, udtThreadInfo.CallbackAddress, %TRUE)
    Exit Function
    Error_SleepForAWhile:
    CALL SendMessage(udtThreadInfo.WindowHandle, %MT_NOTIFY, udtThreadInfo.CallbackAddress, %FALSE)
    End Function
    This code can be perfectly compiled with PowerBasic 8.03. How you can see i modified the part where the original source get a parameter to spawn X number of threads. Because i only need to create one.

    Well, the problem..
    the created thread start to work perfectly but the anomaly is that the principal thread of our vb6 program stop to work. This mean only the function assigned to the thread is working.

    How can i fix that extrange problem ?

    thx

  • #2
    Code:
    IF lngHWnd <> %NULL THEN
      SendMessage lngHWnd, %WM_DESTROY, %FALSE, %FALSE
    End If
    You NEVER "send" WM_DESTROY, you "DestroyWindow" and let Windows handle the WM_DESTROY notification message.

    Or, you can send WM_CLOSE, and Windows will handle destroying the window (if WM_CLOSE is not intercepted in the target window procedure).

    All that said, and with the caveat that I am not a VB guy, I thought anything involving trying to use Microsoft Visual Basic in a multi-threaded process was fraught with "gotchas."

    ALSO: You can't "DestroyWindow" from a thread of execution other than that which owns the window. I can't tell from your code if that is the case here, but if it is then the best thing to do is POST a WM_CLOSE to the target window.


    PS: You want to use the [ c o d e] tags, not the [q u o t e] tags (remove spaces) when posting source code.
    Last edited by Michael Mattias; 18 Dec 2007, 09:20 AM.
    Michael Mattias
    Tal Systems Inc. (retired)
    Racine WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      sorry but i not understood the problem and your solution.
      please can you tell exactly what cause the problem that the original thread of my program is stopped because i started the new trhead ?

      thx


      PD i will edit the code of my first post on the topic using the "code" thing

      Comment


      • #4
        >sorry but i not understood the problem and your solution

        Instead of..
        Code:
        If lngHWnd <> %NULL THEN
          SendMessage lngHWnd, %WM_DESTROY, %FALSE, %FALSE
        End If
        ...do this..
        Code:
        If lngHWnd <> %NULL THEN
          DestroyWindow lngHWnd
        End If
        .. IF executing in same thread of execution, or be TOTALLY safe by doing this...
        Code:
        If lngHWnd <> %NULL THEN
          PostMessage lngHWnd, %WM_CLOSE, %NULL, %NULL
        End If
        .. and you should also hope that someone who knows VB can clarify the whole "VB and multithreading" thing.

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

        Comment


        • #5
          MCM is most likely on the right track, but I will have to wait to get to a machine with VB6 on it.

          One thing you can do to check though is in your %DLL_PROCESS_DETACH is to place a messagebox to tell you the THREADCOUNT.
          (If it is more than 1 then there are still threads open that must be closed or you will crash the VB)

          The other thing you could do is post both your PB Code and your VB Code as they currently are, and one or more of us "VB-Refugee's" may be able to spot where the problem is?
          Engineer's Motto: If it aint broke take it apart and fix it

          "If at 1st you don't succeed... call it version 1.0"

          "Half of Programming is coding"....."The other 90% is DEBUGGING"

          "Document my code????" .... "WHYYY??? do you think they call it CODE? "

          Comment


          • #6
            Most Likely?

            O Ye of Little Faith!
            Michael Mattias
            Tal Systems Inc. (retired)
            Racine WI USA
            [email protected]
            http://www.talsystems.com

            Comment


            • #7
              MCM...I will not rule anything out. and you are NOT god

              Thank God I am Atheist :saythat:

              Anyways back on target....Even without full code to try (or demo to replicate), my gut feeling is the same problem about a thread left open (VB is Notorious for this problem), and it gets worse when you Compile vs Interpret the program in question.

              The other obvious problems that may or may not come into play are Appendix B

              @Alfons
              Well, the problem..
              the created thread start to work perfectly but the anomaly is that the principal thread of our vb6 program stop to work. This mean only the function assigned to the thread is working.
              Can you elaborate a bit? I am having trouble following what the sequence of steps you do to replicate the problem?
              Engineer's Motto: If it aint broke take it apart and fix it

              "If at 1st you don't succeed... call it version 1.0"

              "Half of Programming is coding"....."The other 90% is DEBUGGING"

              "Document my code????" .... "WHYYY??? do you think they call it CODE? "

              Comment


              • #8
                WM_DESTROY is a notification, not a command; it is sent by Windows as part of its entire 'to do' list when you have asked for a window to be destroyed (EndDialog or DestroyWindow, or allowing WM_CLOSE to be handled by default handler).

                "Sending" the WM_DESTROY notification yourself might have some really bad side effects.

                Just think of the things you normally do when you receive the WM_DESTROY notification: you close fiiles, destroy any persistent GDI objects you have created, and frequently PostQuitMessage to terminate message processing for the thread in which the window procedure executes.

                If your program does these things when the window is not destroyed, I'd guess 'acting funny' would be the minimum result.
                Michael Mattias
                Tal Systems Inc. (retired)
                Racine WI USA
                [email protected]
                http://www.talsystems.com

                Comment


                • #9
                  .I seem to remember VB6 notifys windows that it works in a single threaded apartment mode, may be your problem
                  Should have read the aricle first, what is the worker thread doing, does it ever sleep and what version OS
                  Rephrase that need code for 2nd DLL and VB call
                  Last edited by John Petty; 19 Dec 2007, 09:18 AM.

                  Comment


                  • #10
                    Hopefully it is a simple solution
                    In getting PBThread to compile under 8.03 you removed the Alias thus as the declare maybe or the export from PBTHRDWD.DLL depending on what you changed there cannot find the function then it is never being executed.
                    SendMessage does not return until the message is processed by a window that is not created so program just hangs

                    Comment


                    • #11
                      Hi Alfons
                      You just have to love M$ and VB
                      I guess its a SP problem. If I can follow your thinking you modified PBThread and the VB example so nothing worked.
                      The key is you changed the declare and function for SpawnThreads as you only want one thread, if you go back and replace the BYVAL NumberOfThreads AS LONG and recompile the VB you should get a "Type Mismatch" as VB doesn't have a DWORD as in BYVAL CallbackFunctionAddress AS DWORD but if this is the only paramater it can't detect or handle it Duh!!!
                      The solution to your problem is change it in PB to CallbackFunctionAddress AS LONG and everything runs fine. Only other suggestion I can make is SLeep is now a built in function in PB
                      John

                      Comment


                      • #12
                        I did not have time to really research, but I went back to the original tutorial Multi-Threading for Basic Programmers - Part 3: May the "Power" be with You - By Jason Bock to see if there was a problem that existed before you changed the code, and there is.

                        Once you change the code from being hardcoded as the dll being in (I think it was in "C:\Winnt\System32" or something like that) and changing PB Keywords like "THREAD as LONG" or "THREADID as Long" to "MyThreadID AS LONG" so that a keyword is not used,

                        what I found was that the original example worked (I think, but did not have time to check what it was supposed to do) but when you end the VB6-interpreted environment, you would get a crash from VB....leading me to believe 1 or more threads are left open.

                        One bad example would be in the "SpawnThreads" of the PBThread.bas where it has the lines
                        Code:
                                            THREAD CREATE SleepForAWhile(lngHeapPtr) TO lngHThreadResult
                                            THREAD CLOSE lngHThreadResult TO lngRet
                        For the moment, I will just assume that "SleepForAWhile" is just the "Sleep" function, but what I do not like is an immediate release of the handle to the thread although it is most likely still running.

                        Possible crash point there.

                        Just some points of interest to look at

                        Maybe if I can find time, I may come back to those tutorials, and beef them up from an Ex-VB'er point of view (Nice tutorials, but need a lil work code-wise)
                        Engineer's Motto: If it aint broke take it apart and fix it

                        "If at 1st you don't succeed... call it version 1.0"

                        "Half of Programming is coding"....."The other 90% is DEBUGGING"

                        "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                        Comment


                        • #13
                          what I do not like is an immediate release of the handle to the thread although it is most likely still running.

                          Possible crash point there.
                          The hThread returned by THREAD CREATE should be closed if it's not going to be used, just like a file handle or any other handle. This is not a "crash point" at all.

                          Of course once closed any attempt to use this handle will result in failure with an INVALID_HANDLE_VALUE error code (WinAPI calls, don't know what the THREAD xxxx functions will return but I'm sure it's in the help file somewhere).

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

                          Comment


                          • #14
                            The hThread returned by THREAD CREATE should be closed if it's not going to be used, just like a file handle or any other handle.
                            True

                            This is not a "crash point" at all.
                            False...."A running thread is a running thread, regardless if I have a valid handle to it or not"
                            I am thinking something more along the lines of your GUI + Worker Thread + Abort Demo may be a better way to go (but I will admit, I gotta research more before I open my big mouth)

                            Of course once closed any attempt to use this handle will result in failure with an INVALID_HANDLE_VALUE error code (WinAPI calls, don't know what the THREAD xxxx functions will return but I'm sure it's in the help file somewhere).
                            True...an invalid handle is an invalid handle and will "Wreak Havoc" (if you are lucky :laugh:, or make me go even balder :laugh: trying to figure a bug, just to find I had an invalid handle)
                            I know I ran into it a bit ago, but I too will have to look at the docs but a good rule of thumb is, if you release it, make sure you do not have a variable that thinks it still exists.

                            VB can be beast of sorts since there is wide debate about threads (although I do not follow it all correctly) but it is a "Interpreted" language rather than a "Compiled" language. (Or at least VB6 is...not sure about .NOT)
                            Engineer's Motto: If it aint broke take it apart and fix it

                            "If at 1st you don't succeed... call it version 1.0"

                            "Half of Programming is coding"....."The other 90% is DEBUGGING"

                            "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                            Comment


                            • #15
                              A good nights sleep helps, obviously VB cannot determine if a long or dword is required, however changing the declare and function statements even back to dword and it started working.
                              I added a new button to the VB example which just puts some more text in the list which can be clicked at any time to prove the responsiveness of the VB prog
                              here is my code
                              Code:
                              $DEBUG ERROR ON
                              $COMPILE DLL "PBThread.DLL"
                              $INCLUDE "WIN32API.INC"
                              
                              ' CONSTANTS
                              %MAX_SLEEP_TIME = 10000&
                              %MIN_SLEEP_TIME = 1&
                              %MT_NOTIFY = %WM_USER + 800
                              
                              ' TYPES
                              TYPE ThreadPostInfo
                              WindowHandle AS LONG
                              CallbackAddress AS DWORD
                              END TYPE
                              
                              ' GLOBAL VARIABLES
                              GLOBAL glngGeneralMutex AS LONG
                              GLOBAL glngHInstance AS LONG
                              
                              ' FUNCTION/SUB DECLARATIONS
                              DECLARE FUNCTION CreateCallbackWindow LIB "PBThrdWd.Dll" ALIAS "CreateCallbackWindow" (lThreadID AS LONG) AS LONG
                              DECLARE FUNCTION SleepForAWhile(BYVAL lpParam AS LONG) AS LONG
                              DECLARE FUNCTION SpawnThreads (BYVAL CallbackFunctionAddress AS DWORD) AS LONG
                              
                              ' FUNCTION: LibMain
                              FUNCTION LIBMAIN(BYVAL hInstance AS LONG, BYVAL fwdReason AS LONG, BYVAL lpvReserved AS LONG) EXPORT AS LONG
                              ON ERROR RESUME NEXT
                              DIM lngC AS LONG
                              DIM lngRet AS LONG
                              ' Store the instance handle for future reference.
                              glngHInstance = hInstance
                              SELECT CASE fwdReason
                                  CASE %DLL_PROCESS_ATTACH
                                  ' Create the mutex.
                                      glngGeneralMutex = CreateMutex(BYVAL %NULL, %FALSE, BYVAL %NULL)
                                      LIBMAIN = 1
                                      EXIT FUNCTION
                                  CASE %DLL_PROCESS_DETACH
                                  ' Close the mutex.
                                      CloseHandle glngGeneralMutex
                                      LIBMAIN = 1
                                      EXIT FUNCTION
                                  CASE %DLL_THREAD_ATTACH
                                      LIBMAIN = 1
                                      EXIT FUNCTION
                                  CASE %DLL_THREAD_DETACH
                                  ' If a window was created for this thread, destroy it.
                                      DIM ascWindowName AS ASCIIZ * 80
                                      DIM lngHWnd AS LONG
                                      ascWindowName = "MTExample" & STR$(GetCurrentThreadID())
                                      lngHWnd = FindWindow(BYVAL %NULL, ascWindowName)
                                      IF lngHWnd <> %NULL THEN
                                      SendMessage lngHWnd, %WM_DESTROY, %FALSE, %FALSE
                                      END IF
                                      LIBMAIN = 1
                                      EXIT FUNCTION
                              END SELECT
                              ' Any message which is not handled in the above SELECT CASE reaches
                              ' this point and is unknown.
                              END FUNCTION
                              
                              ' FUNCTION: SpawnThreads
                              FUNCTION SpawnThreads ALIAS "SpawnThreads" (BYVAL CallbackFunctionAddress AS DWORD) EXPORT AS LONG
                              ' This function creates a bunch of threads
                              ' and each thread notifies the calling application
                              ' when the work's done.
                              '
                              ' Returns TRUE on success, and FALSE on failure.
                              ON ERROR GOTO Error_SpawnThreads
                              DIM ascWindowName AS ASCIIZ * 80
                              DIM lngHeap AS LONG
                              DIM lngHeapPtr AS LONG
                              DIM lngHThreadResult AS LONG
                              DIM lngHWnd AS LONG
                              DIM lngIndex AS LONG
                              DIM lngLength AS LONG
                              DIM lngRet AS LONG
                              DIM lngThreadID AS LONG
                              DIM udtThreadInfo AS ThreadPostInfo
                              CALL WaitForSingleObject(glngGeneralMutex, %INFINITE)
                              ' Assume a %FALSE for now.
                              FUNCTION = %FALSE
                              ' Create a window if necessary.
                              lngThreadID = GetCurrentThreadID()
                              ascWindowName = "MTExample" & STR$(lngThreadID)
                              lngHWnd = FindWindow(BYVAL %NULL, ascWindowName)
                              IF lngHWnd = %NULL THEN
                                  ' We need to create a window for this thread.
                                  lngHWnd = CreateCallbackWindow(lngThreadID)
                              END IF
                              IF lngHWnd <> 0 THEN
                                  ' Allocate memory in the heap.
                                  lngLength = SIZEOF(udtThreadInfo)
                                  lngHeap = GetProcessHeap
                                  IF lngHeap <> %NULL THEN
                                      ' Create as many threads as needed.
                                      lngHeapPtr = HeapAlloc(lngHeap, 0, lngLength)
                                      IF lngHeapPtr <> 0 THEN
                                          udtThreadInfo.WindowHandle = lngHWnd
                                          udtThreadInfo.CallbackAddress = CallbackFunctionAddress
                                          ' We have success, copy the UDT into the heap.
                                          MoveMemory BYVAL lngHeapPtr, BYVAL VARPTR(udtThreadInfo), lngLength
                                          THREAD CREATE SleepForAWhile(lngHeapPtr) TO lngHThreadResult
                                          THREAD CLOSE lngHThreadResult TO lngRet
                                      END IF
                                      FUNCTION = %TRUE
                                      'FUNCTION = lngHWnd
                                  END IF
                              END IF
                              CALL ReleaseMutex(glngGeneralMutex)
                              EXIT FUNCTION
                              Error_SpawnThreads:
                              CALL ReleaseMutex(glngGeneralMutex)
                              END FUNCTION
                              
                              ' FUNCTION: SleepForAWhile
                              FUNCTION SleepForAWhile(BYVAL HeapPtr AS LONG) AS LONG
                              ' This function will sleep somewhere between
                              ' %MIN_SLEEP_TIME and %MAX_SLEEP_TIME seconds.
                              ' Once it awakes, it'll post a completed message to a hidden window
                              ' and terminate.
                              ON ERROR GOTO Error_SleepForAWhile
                              DIM lngLength AS LONG
                              DIM lngProcessHeap AS LONG
                              DIM lngRet AS LONG
                              DIM lngSleepTime AS LONG
                              DIM udtThreadInfo AS ThreadPostInfo
                              lngLength = SIZEOF(udtThreadInfo)
                              ' We have a pointer to a udt.
                              ' Use CopyMemory and release the memory.
                              MoveMemory BYVAL VARPTR(udtThreadInfo), BYVAL HeapPtr, lngLength
                              ' Now release the memory!
                              lngProcessHeap = GetProcessHeap
                              lngRet = HeapFree(lngProcessHeap, 0, HeapPtr)
                              lngSleepTime = RND(%MIN_SLEEP_TIME, %MAX_SLEEP_TIME)
                              SLEEP lngSleepTime
                              ' Now post a message to the correct window.
                              ' The 3rd parameter is the function address.
                              ' and the 4th signifies success.
                              CALL SendMessage(udtThreadInfo.WindowHandle, %MT_NOTIFY, udtThreadInfo.CallbackAddress, %TRUE)
                              EXIT FUNCTION
                              Error_SleepForAWhile:
                              CALL SendMessage(udtThreadInfo.WindowHandle, %MT_NOTIFY, udtThreadInfo.CallbackAddress, %FALSE)
                              END FUNCTION
                              ps hope you are not trying to run it in the IDE

                              Comment


                              • #16
                                >>This is not a "crash point" at all.
                                > False...."A running thread is a running thread, regardless if I have a valid handle to it or not"

                                As you said yourself..
                                ...I gotta research more before I open my big mouth...
                                That a thread function is still executing has absolutely zero (none, nada, zip, squat) relationship to the number of open handles to the thread object. And when you think about it just a little , you understand that is fundamental: you USE the handle to query the status of the thread function: Is is still executing (exit code=STILL_ACTIVE), or has it ended and assigned a return value?

                                That is, failure to close a handle to a thread object cannot and will not cause a program to "crash."

                                Trying to USE an invalid ("closed") handle to a thread object without proper error testing "can" cause a program to "crash" ; then again, so can dividing by a variable whose value you have set to zero.

                                MCM
                                Last edited by Michael Mattias; 20 Dec 2007, 08:26 AM.
                                Michael Mattias
                                Tal Systems Inc. (retired)
                                Racine WI USA
                                [email protected]
                                http://www.talsystems.com

                                Comment

                                Working...
                                X