Announcement

Collapse
No announcement yet.

Download Code uses 100% CPU

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

  • Download Code uses 100% CPU

    What am I doing wrong here? This is the working code for the
    download manager I am writing. If your on high bandwidth connection
    and you load an M3u file or a txt file you will see what I'm
    talking about.

    Any suggestions on making it use less CPU would be appreciated.

    I know it isn't the threads because if you take out all TCP
    functions, everything is good. Something with my TCP code maybe.

    Lance, I also know, this isn't thread safe yet

    if you need an M3U file you can get one here:
    http://play.mp3.com/cgi-bin/play/play.c gi/AAIBQgAAAADABG5vcm1QBAAAAFItDAMAUQoAAABYAQAAAFktDAMAQ4800TtHmsiK8JO1KU87PXfW4WzQ/mlm_king.m3u
    Code:
    #COMPILE EXE
    #INCLUDE "win32api.inc"
    #INCLUDE "commctrl.inc"
    #INCLUDE "comdlg32.inc"
    
    #RESOURCE "d:\pbdll60\samples\tray\tray.pbr"
    GLOBAL pbStep AS LONG, OldLvProc AS LONG
    GLOBAL hListView AS LONG
    
    %LISTVIEW1 = 100
    %MNU_LOAD_DOWNLOADLIST = 500
    %MNU_OPTIONS = 501
    %MNU_EXIT = 502
    %WM_PRINT = &H317
    
    TYPE UrlStruct
      sURL AS STRING * 512
      nProgress AS LONG
      nSize AS LONG
    END TYPE
    
    GLOBAL gURL() AS UrlStruct
    GLOBAL ofn AS OPENFILENAME
    GLOBAL gCommand$    'global command line params
    
    '------------------------------------------------------------------------------
    FUNCTION GetFileNameProc (BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG
          LOCAL rc1 AS Rect, rc2 AS Rect, hWnd1 AS LONG, hWnd2 AS LONG
          SELECT CASE wMsg
             CASE %WM_SIZE
                hWnd1 = GetParent(hWnd)
                ' Center
                hWnd2 = ofn.hWndOwner: IF hWnd2 = 0 THEN hWnd2 = GetDesktopWindow
                GetWindowRect hWnd1, rc1: GetWindowRect hWnd2, rc2
                SetWindowPos hWnd1, %HWND_TOPMOST, _
                   rc2.nLeft  + ((rc2.nRight - rc2.nLeft) - (rc1.nRight - rc1.nLeft)) / 2, _
                   rc2.nTop   + ((rc2.nBottom - rc2.nTop) - (rc1.nBottom - rc1.nTop)) / 2, _
                   0, 0, %SWP_NOSIZE
                ' Set names
                SetWindowText hWnd1, "Please Select Download File List"
                DIM TmpAsciiz AS ASCIIZ * 255
                TmpAsciiz = "Folder"  : _
                   SendMessage hwnd1, %CDM_SETCONTROLTEXT, &H443, VARPTR(TmpAsciiz)
                TmpAsciiz = "Download List": _
                   SendMessage hwnd1, %CDM_SETCONTROLTEXT, &H442, VARPTR(TmpAsciiz)
                TmpAsciiz = "Type": _
                   SendMessage hwnd1, %CDM_SETCONTROLTEXT, &H441, VARPTR(TmpAsciiz)
                TmpAsciiz = "&Okay"      : SendMessage hwnd1, %CDM_SETCONTROLTEXT, _
                   %IDOK, VARPTR(TmpAsciiz)
                TmpAsciiz = "&Exit"  : SendMessage hwnd1, %CDM_SETCONTROLTEXT, _
                   %IDCANCEL, VARPTR(TmpAsciiz)
          END SELECT
          FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)
       END FUNCTION
    '------------------------------------------------------------------------------
    FUNCTION GetFileName(hWnd AS LONG) AS STRING
          STATIC szCurDir1 AS ASCIIZ * %MAX_PATH, szCurDir2 AS ASCIIZ * %MAX_PATH
          STATIC szTitleName AS ASCIIZ * %MAX_PATH, _
                 szFilter AS ASCIIZ * %MAX_PATH
          IF ofn.lStructSize = 0 THEN
             ofn.lStructSize = SIZEOF(ofn)
             ofn.hWndOwner = hWnd
             szFilter = "M3U Files (*.m3u)" + CHR$(0) + "*.m3u" + CHR$(0) + _
                "All Files (*.*)" + CHR$(0) + "*.*" + CHR$(0)
             ofn.lpstrFilter = VARPTR(szFilter)
             ofn.lpstrFileTitle = VARPTR(szTitleName)
             ofn.nMaxFileTitle = SIZEOF(szTitleName)
             ofn.lpfnHook = CODEPTR(GetFileNameProc)
             ofn.Flags = %OFN_HIDEREADONLY OR %OFN_CREATEPROMPT OR %OFN_EXPLORER OR %OFN_ENABLEHOOK
          END IF
          GetCurrentDirectory SIZEOF(szCurDir1), szCurDir1
          GetOpenFileName ofn
          GetCurrentDirectory SIZEOF(szCurDir2), szCurDir2
          IF RIGHT$(szCurDir2, 1) <> "\" THEN szCurDir2 = szCurDir2 + "\"
          IF szTitleName = "" THEN FUNCTION = "" ELSE FUNCTION = szCurDir2 + szTitleName
          SetCurrentDirectory szCurDir1
       END FUNCTION
    '------------------------------------------------------------------------------
    SUB LV_AddItem(hListView&, sTitle$, lMask&, lStateMask&, lPos&)
      LOCAL azItemText AS ASCIIZ * %MAX_PATH
      LOCAL lvITEM AS LV_ITEM
      azItemText = sTitle$
      lvITEM.iImage = 0
      lvITEM.iItem = ListView_GetItemCount(hListView)
      lvITEM.mask = %LVCF_FMT OR %LVCF_WIDTH OR  %LVCF_TEXT OR %LVCF_SUBITEM
      lvITEM.stateMask =  lStateMask&
      lvITEM.pszText = VARPTR(azItemText)
      lStatus& = ListView_InsertItem (hListView, lvITEM)
    END SUB
    '------------------------------------------------------------------------------
    SUB LV_CreateColumn(hListView&, sTitle$, lMask&, lWidth&, lPos&)
      LOCAL azTitle AS ASCIIZ * 25
      LOCAL Column AS LV_COLUMN
    
      azTitle = sTitle$
      Column.mask = lMask&
      Column.fmt = %LVCFMT_LEFT
      Column.cx = lWidth&
      Column.pszText = VARPTR(azTitle)
      ListView_InsertColumn hListView, lPos&, Column
    END SUB
    '------------------------------------------------------------------------------
    FUNCTION LVW_GetSelected(hListView&) AS LONG
      ListCount& = ListView_GetItemCount(hListView)
      FOR a& = 0 TO ListCount&
          r& = ListView_GetItemState(hListView,a&,%LVIS_FOCUSED)
          IF r& = %LVIS_FOCUSED THEN
              FUNCTION = a&
              EXIT FUNCTION
          END IF
      NEXT
     END FUNCTION
    '------------------------------------------------------------------------------
    FUNCTION GetHost(URL$) AS STRING
        sBuffer$ = UCASE$(URL$)
        sBuffer$ = REMAIN$(sBuffer$, "HTTP://")
        sBuffer$ = EXTRACT$(sBuffer$, "/")
        FUNCTION = sBuffer$
    END FUNCTION
    '------------------------------------------------------------------------------
    FUNCTION GetHTTPFileSize(URL$, FileNum&) AS LONG
        STATIC Count&
    
        IF Count& > 5 THEN
            DO UNTIL count& < 5
                SLEEP 1
            LOOP
        END IF
        INCR Count&
    
    
        LOCAL ff AS LONG, rtn AS STRING, dsp AS STRING
        rtn=TRIM$(URL$)
    
        IF rtn = "" THEN
           FUNCTION = -1: EXIT FUNCTION
        END IF
    
        sHost$ = GetHost(URL$)
    
        REPLACE "http://" WITH "" IN rtn
        ff=FileNum&
        TCP OPEN PORT 80 AT sHost$ AS ff
        TCP PRINT ff, "GET <A HREF="http://"" TARGET=_blank>http://"</A>  & rtn & " HTTP/1.0" & CHR$(13,10,13,10)
        TCP RECV ff, 500, rtn
        TCP CLOSE ff
        'MSGBOX rtn
        IF INSTR(rtn,CHR$(13)) = 0 THEN REPLACE CHR$(10) WITH CHR$(13,10) IN rtn
        rtn = UCASE$(rtn)
        rtn = REMAIN$(rtn, "CONTENT-LENGTH:")
        rtn = EXTRACT$(rtn, CHR$(13))
        FUNCTION = VAL(TRIM$(rtn))
        DECR Count&
    END FUNCTION
    '------------------------------------------------------------------------------
    FUNCTION GetURL(BYVAL x AS LONG) AS LONG
      LOCAL FF AS LONG
      LOCAL I AS LONG, zTxt AS ASCIIZ * 20
      STATIC Count&
    
      sText$ = TRIM$(gURL(x).sURL)
      sText$ = PARSE$(sText$, "/", PARSECOUNT(sText$, "/"))
    
      LV_AddItem hListView, BYCOPY sText$, %LVCF_FMT OR %LVCF_WIDTH OR  %LVCF_TEXT OR %LVCF_SUBITEM, %LVIS_FOCUSED, 0
      ListView_SetItemText hListView, x, 1, "quead"
      ListView_SetItemText hListView, x, 2, "getting filesize"
      SLEEP RND(1000, 3000)
      FileSize& = GetHTTPFileSize(TRIM$(gURL(x).sURL), x)
      gURL(x).nSize = FileSize&
      ListView_SetItemText hListView, x, 2, FORMAT$(FileSize&\1024) & "K"
    
      'We want it to wait till we are free
      IF Count& > 5 THEN
      DO UNTIL count& < 5
        SLEEP 1000
      LOOP
      END IF
      INCR Count&
    
      'Get Host Name
    
      pbStep = 1
      sURL$ = TRIM$(gURL(x).sURL)
      sHost$ = GetHost(TRIM$(gURL(x).sURL))
      REPLACE "http://" WITH "" IN sURL$
      ff=X   'Use Array Pointer for FileNumber
      TCP OPEN PORT 80 AT sHost$ AS ff
      TCP PRINT ff, "GET <A HREF="http://"" TARGET=_blank>http://"</A>  & sURL$ & " HTTP/1.0" & CHR$(13,10,13,10)
      DO
        TCP RECV ff, 4096, sBuffer$
        sTemp$ = sTemp$ & sBuffer$
        PerCentage& = (LEN(sTemp$) / gURL(x).nSize) * 100
        ListView_SetItemText hListView, x, 1, FORMAT$(PerCentage&)
        SLEEP 100
      LOOP WHILE LEN(sBuffer$)
      sBuffer$ = REMAIN$(sTemp$, $CRLF & $CRLF)
    
      TCP CLOSE ff
    
      OPEN "C:\TEMP" & "\" & sText$ FOR BINARY AS ff
         SETEOF ff
         PUT$ ff, sBuffer$
      CLOSE ff
      ListView_SetItemText hListView, x, 1, "Done!"
      DECR Count&
    END FUNCTION
    '------------------------------------------------------------------------------
    SUB AddURL(URL$)
      STATIC qID&
      gURL(qID&).sURL = URL$
      THREAD CREATE GetUrl(qID&) TO woot&
      THREAD CLOSE woot& TO woot&
      INCR qID&
    END SUB
    '------------------------------------------------------------------------------
    SUB ProcessList(sPath$)
        FileNum& = FREEFILE
        OPEN sPath$ FOR BINARY AS FileNum&
        GET$ FileNum&, LOF(FileNum&), sBuffer$
        CLOSE FileNum&
    
        REPLACE CHR$(10, 13) WITH CHR$(13) IN sBuffer$
        REPLACE CHR$(13, 10) WITH CHR$(13) IN sBuffer$
        REPLACE CHR$(10) WITH CHR$(13) IN sBuffer$
        FOR lCounter& = 0 TO PARSECOUNT(sBuffer$, CHR$(13))
            sURL$ = PARSE$(sBuffer$, CHR$(13), lCounter&)
            sURL$ = UCASE$(sURL$)
            IF LEFT$(sURL$, 4) = "HTTP" THEN
               AddURL(PARSE$(sBuffer$, CHR$(13), lCounter&))
            END IF
        NEXT
    END SUB
    '------------------------------------------------------------------------------
    FUNCTION WndProc (BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, _
                      BYVAL wParam AS LONG, BYVAL lParam AS LONG) EXPORT AS LONG
      LOCAL rect AS rect, zTxt AS ASCIIZ * 260
      LOCAL LV_LpLvNm AS NM_LISTVIEW PTR
    
      SELECT CASE wMsg
         CASE %WM_NOTIFY
            SELECT CASE LOWRD(wParam)
               CASE %LISTVIEW1
                  LV_LPLVNM = lParam
                  SELECT CASE @LV_LPLVNM.HDR.CODE
                     CASE %NM_CLICK
                     CASE %NM_RCLICK
                     CASE %LVN_COLUMNCLICK
                  END SELECT
            END SELECT
            '================================================
    
         CASE %WM_CREATE
            MENU NEW BAR TO hMenu0&
            MENU NEW POPUP TO hMenu1&
            MENU ADD POPUP, hMenu0& ,"&File", hMenu1&, %MF_ENABLED
            MENU ADD STRING, hMenu1&, "&Load Download List",  %MNU_LOAD_DOWNLOADLIST, %MF_ENABLED
            MENU ADD STRING, hMenu1&, "-",  0, %MF_ENABLED
            MENU ADD STRING, hMenu1&, "Options",  %MNU_OPTIONS, %MF_ENABLED
            MENU ADD STRING, hMenu1&, "E&xit",  %MNU_EXIT, %MF_ENABLED
            MENU ATTACH hMenu0&, hWnd
    
            GETCLIENTRECT hWnd, rect
            hListView = CREATEWINDOW ( "SysListView32", _
                        "", _
                        %WS_border OR %WS_Child OR %WS_visible OR _
                        %LVS_Report OR %LVS_SINGLESEL OR %LVS_SHOWSELALWAYS OR %LVS_OWNERDRAWFIXED OR %LVS_NOCOLUMNHEADER, _
                        0, _
                        0, _
                        rect.nRight - 1, _
                        rect.nBottom - 1, _
                        hWnd, _
                        %LISTVIEW1, _
                        GETMODULEHANDLE(BYVAL 0&), _
                        %Null )
            OldLvProc = SetWindowLong(hListView, %GWL_WNDPROC, CODEPTR(LvSubClass))
    
            LV_CreateColumn hListView, "Downloading", %LVCF_FMT OR %LVCF_WIDTH OR %LVCF_TEXT OR %LVCF_SUBITEM, 300, 0
            LV_CreateColumn hListView, "Progress", %LVCF_FMT OR %LVCF_WIDTH OR %LVCF_TEXT OR %LVCF_SUBITEM, 200, 1
            LV_CreateColumn hListView, "Size", %LVCF_FMT OR %LVCF_WIDTH OR %LVCF_TEXT OR %LVCF_SUBITEM, 100, 2
            IF LEN(DIR$(gCOMMAND$)) = 0 THEN
                gCOMMAND$ = GetFileName(hWnd)
            END IF
    
            IF LEN(DIR$(gCOMMAND$)) > 0 THEN
                ProcessList gCOMMAND$
                    ELSE
                POSTQUITMESSAGE 0
            END IF
           '================================================
    
         CASE %WM_DRAWITEM
            IF wParam = %LISTVIEW1 THEN
               LOCAL cw1 AS LONG, cw2 AS LONG, cw3 AS LONG, cw4 AS LONG, rc AS RECT
               LOCAL ClientArea AS RECT
               LOCAL lpdis AS DRAWITEMSTRUCT PTR
    
               lpdis = lParam
    
               SELECT CASE @lpdis.itemAction
                  CASE %ODA_DRAWENTIRE, %ODA_SELECT
                     'CLEAR BACKGROUND
                     ListView_GetItemRect hListView, @lpdis.itemID, rc, %LVIR_BOUNDS
                     cw1 = ListView_GetColumnWidth(hListView, 0)
                     cw2 = ListView_GetColumnWidth(hListView, 1)
                     cw3 = ListView_GetColumnWidth(hListView, 2)
    
                     rc.nLeft = 0 : rc.nRight = cw1+cw2+cw3
    
                     IF (@lpdis.itemState AND %ODS_SELECTED) THEN
                        FillRect @lpdis.hDC, rc, GetSysColorBrush(%COLOR_HIGHLIGHT)
                        SetBkColor @lpdis.hDC, GetSysColor(%COLOR_HIGHLIGHT)
                        SetTextColor @lpdis.hDC, GetSysColor(%COLOR_HIGHLIGHTTEXT)
                     ELSE
                        FillRect @lpdis.hDC, rc, GetSysColorBrush(%COLOR_WINDOW)
                        SetBkColor @lpdis.hDC, GetSysColor(%COLOR_WINDOW)
                        SetTextColor @lpdis.hDC, GetSysColor(%COLOR_WINDOWTEXT)
                     END IF
    
                     'COLUMN 1
                     CALL ListView_GetItemText(hListView, @lpdis.itemID, 0, zTxt, SIZEOF(zTxt))
                     rc.nLeft = 2
                     DrawText @lpdis.hDC, zTxt, LEN(zTxt), rc, %DT_LEFT OR %DT_SINGLELINE OR %DT_VCENTER
                     'DRAW FOCUSRECT (if control has focus)
                     IF (@lpdis.itemState AND %ODS_SELECTED) AND GetFocus = hListView THEN 'if selected + focus
                        rc.nLeft = 0
                        CALL DrawFocusRect(@lpdis.hDC, rc) 'draw focus rectangle
                     END IF
    
                     'COLUMN 2
                     CALL ListView_GetItemText(hListView, @lpdis.itemID, 1, zTxt, SIZEOF(zTxt))
                     IF VAL(zTxt) > 0 THEN
                        rc.nLeft  = cw1
                        rc.nRight = cw1 + cw2 * VAL(zTxt) / 100
                        FillRect @lpdis.hDC, rc, GetSysColorBrush(%COLOR_3DFACE)
                        DrawEdge @lpdis.hDC, rc, %BDR_RAISEDINNER, %BF_RECT
    
                        rc.nLeft  = rc.nRight
                        rc.nRight = cw1 + cw2
                        FillRect @lpdis.hDC, rc, GetSysColorBrush(%COLOR_WINDOW)
    
                        rc.nLeft = cw1
                        SetBkMode @lpdis.hDC, %TRANSPARENT
                        SetTextColor @lpdis.hDC, %BLUE
                        zTxt = zTxt + "%"
                        INCR rc.nTop
                        DrawText @lpdis.hDC, zTxt, LEN(zTxt), rc, %DT_CENTER OR %DT_SINGLELINE OR %DT_VCENTER
                            ELSE
                        rc.nLeft  = cw1
                        rc.nRight = cw1 + cw2 * VAL(zTxt) / 100
                        FillRect @lpdis.hDC, rc, GetSysColorBrush(%COLOR_WINDOW)
    
                        rc.nLeft  = rc.nRight
                        rc.nRight = cw1 + cw2
                        FillRect @lpdis.hDC, rc, GetSysColorBrush(%COLOR_WINDOW)
    
                        rc.nLeft = cw1
                        SetBkMode @lpdis.hDC, %TRANSPARENT
                        SetTextColor @lpdis.hDC, %Gray
                        DrawText @lpdis.hDC, zTxt, LEN(zTxt), rc, %DT_CENTER OR %DT_SINGLELINE OR %DT_VCENTER
                     END IF
    
                    'COLUMN 3
    
                     IF (@lpdis.itemState AND %ODS_SELECTED) THEN
                            SetBkColor @lpdis.hDC, GetSysColor(%COLOR_HIGHLIGHT)
                            SetTextColor @lpdis.hDC, GetSysColor(%COLOR_HIGHLIGHTTEXT)
                        ELSE
                            SetBkColor @lpdis.hDC, GetSysColor(%COLOR_WINDOW)
                            SetTextColor @lpdis.hDC, %RED 'GetSysColor(%COLOR_WINDOWTEXT)
                     END IF
                     CALL ListView_GetItemText(hListView, @lpdis.itemID, 2, zTxt, SIZEOF(zTxt))
                     rc.nLeft = cw1+cw2
                     rc.nRight = cw1+cw2+cw3
                     DrawText @lpdis.hDC, zTxt, LEN(zTxt), rc, %DT_CENTER OR %DT_SINGLELINE OR %DT_VCENTER
    
                    'COLUMN.. the rest..
                     GetClientRect hListView, rc
                     rc.nLeft  = cw1 + cw2 + cw3 'add up column widths and see if we have something left to paint
                     IF rc.nLeft < rc.nRight THEN FillRect @lpdis.hDC, rc, GetSysColorBrush(%COLOR_WINDOW)
    
                     FUNCTION = %TRUE : EXIT FUNCTION
    
               END SELECT
            END IF
            '================================================
    
         CASE %WM_DESTROY
            IF OldLvProc THEN SETWINDOWLONG hListView, %GWL_WNDPROC, OldLvProc
            POSTQUITMESSAGE 0
    
      END SELECT
    
      FUNCTION = DEFWINDOWPROC(hWnd, wMsg, wParam, lParam)
    END FUNCTION
    '------------------------------------------------------------------------------
    FUNCTION WINMAIN (BYVAL hInstance     AS LONG, _
                      BYVAL hPrevInstance AS LONG, _
                      lpCmdLine           AS ASCIIZ PTR, _
                      BYVAL iCmdShow      AS LONG) AS LONG
    
      LOCAL Msg         AS tagMsg
      LOCAL wndclass    AS WndClassEx
      LOCAL szClassName AS ASCIIZ * 80
      LOCAL hWnd        AS LONG
      LOCAL CC1 AS INIT_COMMON_CONTROLSEX
      REDIM gURL(10000) AS UrlStruct
    
      gCommand$ = COMMAND$
      REPLACE CHR$(34) WITH "" IN gCommand$
    
      CC1.dwSize=SIZEOF(CC1)
      CC1.dwICC=%ICC_WIN95_CLASSES
      INITCOMMONCONTROLSEX CC1
    
    
      szClassName            = "SDK_LISTVIEW"
      wndclass.cbSize        = SIZEOF(WndClass)
      wndclass.style         = %CS_HREDRAW OR %CS_VREDRAW
      wndclass.lpfnWndProc   = CODEPTR( WndProc )
      wndclass.cbClsExtra    = 0
      wndclass.cbWndExtra    = 0
      wndclass.hInstance     = hInstance
      wndclass.hIcon         = LOADICON( hInstance, "FACE1")
      wndclass.hCursor       = LOADCURSOR( %NULL, BYVAL %IDC_ARROW )
      wndclass.hbrBackground = GETSTOCKOBJECT( %GRAY_BRUSH )
      wndclass.lpszMenuName  = %NULL
      wndclass.lpszClassName = VARPTR( szClassName )
      wndclass.hIconSm       = 0
      REGISTERCLASSEX wndclass
    '
      hWnd = CREATEWINDOWEX(%WS_EX_TOPMOST, _
                            szClassName, _
                            "WebGet 1.0", _
                            %DS_CENTER _
                            OR %WS_CAPTION  _
                            OR %WS_SYSMENU , _
                            0, _
                            0, _
                            700&, _
                            300&, _
                            %NULL, _
                            %NULL, _
                            hInstance, _
                            BYVAL %NULL)
    
      SHOWWINDOW hWnd, iCmdShow
      ghWnd& = hWnd
      UPDATEWINDOW hWnd
    
      WHILE ISTRUE GETMESSAGE(Msg, %NULL, 0, 0)
         TRANSLATEMESSAGE msg
         DISPATCHMESSAGE msg
      WEND
      SLEEP 1
      FUNCTION = msg.wParam
    
    END FUNCTION
    '------------------------------------------------------------------------------
    CALLBACK FUNCTION LvSubClass
      SELECT CASE CBMSG
         CASE %WM_NCPAINT 'something triggered repaint, allow it to happen
            pbStep = 0
    
         CASE %WM_ERASEBKGND
            IF pbStep THEN   'prevent repaints during progress
               FUNCTION = 1 : EXIT FUNCTION
    
            ELSE             'but sometimes need to ignore and repaint..
               pbStep = 1
            END IF
    
      END SELECT
      FUNCTION = CallWindowProc(OldLvProc, CBHNDL, CBMSG, CBWPARAM, CBLPARAM)
    END FUNCTION
    ------------------
    -Greg



    [This message has been edited by Gregery D Engle (edited October 20, 2001).]
    -Greg
    [email protected]
    MCP,MCSA,MCSE,MCSD

  • #2
    Nope. I'm using Win2K with ADSL, I only see 100% CPU during the initial dialog drawing. After that the CPU usage is almost non-existant (ie, very low).

    Uh, is this ment to GET the file too? I tested it with the M3U file you denoted, and it "gets the filesize" and stops... is that right?


    ------------------
    Lance
    PowerBASIC Support
    mailto:[email protected][email protected]</A>
    Lance
    mailto:[email protected]

    Comment


    • #3
      I rechecked the MPU file link and it says "my trial membership does not allow me to play the file".

      Actually, I don't have a membership at all.


      ------------------
      Lance
      PowerBASIC Support
      mailto:[email protected][email protected]</A>
      Lance
      mailto:[email protected]

      Comment


      • #4
        Lance,

        Yes it's supposed to get the file and put it in the C:\TEMP folder.

        Maybe since you don't have a membership it doesn't work with that
        M3U

        In any cause you can use a standard text file with a URL and a CR
        at the end of each line.

        I was going to post a sample download list that I compiled by finding
        games that are over 1 or 2 megs but everytime I post it on here, it puts
        the UBB [url] tags around them. How do I disable that?

        Anyways I'm going to send everything in zip format to you.

        If anyone else has suggestions please let me know.

        In the zip file there is a file called List.TXT, on my PC if I
        load that file my app takes about 80 to 99% cpu usuage. I just
        don't understand why.

        ------------------
        -Greg



        [This message has been edited by Gregery D Engle (edited October 20, 2001).]
        -Greg
        [email protected]
        MCP,MCSA,MCSE,MCSD

        Comment


        • #5
          Greg, the code seems to have a few problems. Using the LIST file you sent to me, here are some of the results:
          Code:
          DMINST.EXE  -2147483648  OK
          ...
          KARNAGE.ZIP 449%  OK
          ..
          psycospawn.zip 135% OK
          I can email you a BMP if you like, but the bizarre percentages indicate some form of unexpected behavior.

          I don't have time right now to dive into this deeply, but I do suspect that you need to pay some attention to thread-safe practices.

          For example, the STATIC COUNT& var in the thread function should be wrapped in a critical section as it's operation is too sensitive to context switching between threads.

          Also, there is no checking for TCP errors in the thread function.

          If I have more time available, I'd certainly like to help you debug this further, however, Bob is keeping me pretty busy!

          ------------------
          Lance
          PowerBASIC Support
          mailto:[email protected][email protected]</A>
          Lance
          mailto:[email protected]

          Comment


          • #6
            Lance,

            That's really weird. It works fine on my PC.

            By the way, the source code I sent you I modified since the
            original. Maybe you were using the original one posted here?

            See the first post:

            Lance, I also know, this isn't thread safe yet
            I knew you would bring that up. I will modify my code to
            fix that and see if that changes anything.

            Thanks for your help.


            ------------------
            -Greg
            -Greg
            [email protected]
            MCP,MCSA,MCSE,MCSD

            Comment


            • #7
              For the purposes of testing, I would remove all the COUNT& related code. I can't see what you use two "5 limit" blocks either... there is no reason you can;t get the filesize for 500 files at the same time if need be, but just do the file GET in smaller groups.

              Anyway, as I said, remove that code until you get the rest of it sorted out.

              BTW, I modified the code slightly after dinner, and all of the files listed in your LIST.M3U file return an error 404 which gets saved to disk in the specified filename (EXE, ZIP, etc)!

              ie, you may need to add some code to examine the returned data for HTML code rather than the expected data, and also check for an ERR condition in the TCP RECV loop.

              Good luck!

              ------------------
              Lance
              PowerBASIC Support
              mailto:[email protected][email protected]</A>
              Lance
              mailto:[email protected]

              Comment


              • #8
                I was looking at that Count& stuff, too

                Seems to me when Count& is > 5 this code can never do anything but sit in an endless loop, unless another thread is running and resets Count&; this seems a "unique" (?) way of controlling the usage count.

                Code:
                STATIC Count&
                    IF Count& > 5 THEN
                        DO UNTIL count& < 5 
                           SLEEP 1
                        LOOP
                    END IF
                    INCR Count&
                This appears in (at least) two procedures.

                I posted some code with a title of "Simple Job Queue" or something like that (search by my user id in Source Code Forum to find it). That code uses a "Dispatcher" function to control the execution of multiple threads. While that code was designed to allow one thread at a time, it should not be too difficult to modify to support some kind of "max worker thread" count.

                A couple of other 'thread-safety' notes:

                1. When I was developing a new version of this queue process, I ran into some problems with not being able to keep the stack clean when firing off multiple "worker threads" in rapid succession; that is, the parameters the thread got did not seem distinct. I solved that by adding a "SLEEP 500" statement after every call to CREATE THREAD to allow the stack to clear. Your "high-bandwidth" criteria might be bumping up against this same phenomenon.

                2. A post here recently by Mr. Hanlin indicated there might be some changes in the way thread functions can be used in future versions of PB. You may wish to contact PB support to see if you can get some additional info on that should you be planning to go with the newer version of PB/DLL when available.

                3. Look into Thread Local Storage to avoid GLOBAL/STATIC data collisions.



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

                Comment


                • #9
                  Lance,

                  I also got a 404 error but I changed the line(s)

                  TCP PRINT ff, "GET <A HREF="http://"" TARGET=_blank>http://"</A> & sURL$ & "/ HTTP/1.0"

                  to

                  TCP PRINT ff, "GET <A HREF="http://"" TARGET=_blank>http://"</A> & sURL$ & " HTTP/1.0"

                  That fixed the 404 error, but your correct I think I need to
                  check and see if it's an error when I check the filesize.

                  I will try turning off the GetFile function entirely and turn
                  off limiting the GetFileSize function. And see if that helps.
                  If I remember correctly, if you add about 500 entries the
                  program becomes unresponsive. I'll have to check on that again.

                  Michael,

                  I'll have to take a look at your code, thanks for the suggestion

                  ------------------
                  -Greg

                  [This message has been edited by Gregery D Engle (edited October 21, 2001).]
                  -Greg
                  [email protected]
                  MCP,MCSA,MCSE,MCSD

                  Comment


                  • #10
                    Originally posted by Michael Mattias:
                    2. A post here recently by Mr. Hanlin indicated there might be some changes in the way thread functions can be used in future versions of PB. You may wish to contact PB support to see if you can get some additional info on that should you be planning to go with the newer version of PB/DLL when available.
                    There is nothing in the thread facets of this code that will cause any problems.

                    How can I tell? Simple: Gregery is using the THREAD CREATE statement to initiate his threads, and he is not calling the thread function any other way (directly with the CALL statement, as a direct function execution, or using the CreateThread() API).

                    The forthcoming restriction that Tom mentioned is likely to only affect code that launches a thread or calls a thread function without using the THREAD CREATE statement.



                    ------------------
                    Lance
                    PowerBASIC Support
                    mailto:[email protected][email protected]</A>
                    Lance
                    mailto:[email protected]

                    Comment


                    • #11
                      The forthcoming restriction that Tom mentioned is likely to only affect code that launches a thread or calls a thread function without using the THREAD CREATE statement.
                      Which restriction - if implemented by PowerBASIC, Inc, that is - makes the code to which I referred Mr. Engle (the job queue) directly in violation with what will probably be the documentation for such new restriction, if such restriction is in fact implemented.

                      So, while Mr. Engle's current code is unaffected, I'd hate to have him re-code his application based on my suggestion, only to have the work required to implement that coding technique negated by a change in the compiler product.

                      MCM
                      (Did I put enough disclaimers in this?)
                      Michael Mattias
                      Tal Systems (retired)
                      Port Washington WI USA
                      [email protected]
                      http://www.talsystems.com

                      Comment


                      • #12
                        My point is that Gregery's code is fine as posted above in regard to initiating multiple threads, and as such is not at risk of compatibility with future versions of PowerBASIC.

                        Michael, your code is another matter altogether. If you consider your specific source code posting to be at risk of compatibility with future versions of PowerBASIC (as described by Tom and myself in recent days), you may wish to edit your source code posting(s) and add a suitable note to inform potential users that the code may use unsupported techniques to initiate thread functions and list the specific versions of PowerBASIC that you are personally sure it works with.



                        PS: PowerBASIC have never stated or documented that a Thread function could be called directly or launched with the CreateThread() API. The documentation describes the use of the THREAD CREATE statement only. Possibly this may change.

                        ------------------
                        Lance
                        PowerBASIC Support
                        mailto:[email protected]suppor[email protected]</A>
                        Lance
                        mailto:[email protected]

                        Comment


                        • #13
                          Lance, I think PowerBASIC has not "documented" specifically any win32 API calls
                          which are or are not supported but has quite clearly conveyed that all are usable.
                          I had always presumed ANY win32 api function was usable based upon what information
                          was published by PowerBASIC marketing/sales and due to the fact that I was/am
                          aware of no win32 API functions which have been officially documented as
                          unsupported by PowerBASIC. This said, I had used the CreateThread() api for
                          over two years in an application with more than 15 threads. I have noticed no
                          change in behavior since converting it to use the PB runtime Thread
                          arsenal a couple weeks ago. It is a little confusing when bullet statements
                          like the following are read about a product:
                          Complete access to the entire Win32 API, including ODBC and TAPI
                          A bullet does attempt to drive home a major point. I think I interpreted that
                          statement correctly - at face value. "Complete access" to the "entire" anything
                          is quite encompassing.

                          That said, I have converted to the Thread statement after Tom informed me
                          CreateThread() was not recommended by R&D. This did bring up a new question?
                          What win32 APIs are recommended or are not recommended? Apparently there is no
                          compiled list to refer to for the answer.

                          Ron

                          Comment


                          • #14
                            PS: PowerBASIC have never stated or documented that a Thread function could be called directly or launched with the CreateThread() API. The documentation describes the use of the THREAD CREATE statement only. Possibly this may change.
                            1. I am with Mr Pierce on this.

                            2. If there will be changes in the PowerBASIC compiler products which result in "non-backward compatibility other than new keywords" I repeat my posting here of a few weeks ago and my email to support from two weeks prior to that with a copy to you:

                            "It's fine to withhold premature announcement of new features, but it is absolutely OK - nay, encouraged - that PowerBASIC announce as soon as possibile any upcoming limitations which will result in such incompatibilities."

                            I'm sure PowerBASIC Inc has the finest compiler writers in the galaxy, but those of us at the sharp end of the applications stick have a different view of what is important, and when it is important.

                            MCM


                            [This message has been edited by Michael Mattias (edited October 21, 2001).]
                            Michael Mattias
                            Tal Systems (retired)
                            Port Washington WI USA
                            [email protected]
                            http://www.talsystems.com

                            Comment


                            • #15
                              Guys, to be clear, we have NOT said you cannot use the CreateThread() API at all, ever again. For example, you can still use CreateThread(), say, with a DLL created with C, or any API that is itself a thread function, etc. In that circumstance, CreateThread() is the method of choice.

                              However, if you wish to launch a high-level PowerBASIC thread function then you simply launch it with the high-level THREAD CREATE statement. Nothing too difficult about that, right?

                              Basically, there are no API functions that you cannot call. However, there are circumstances where you may or may not be wise to call an API - it depends on the context of YOUR code. As such, there are no documents that describe any API's which are "not allowed" to be used.

                              Essentially, it is up to you, the programmer, to choose the best statement, function or API call for each specific aspect of your code.

                              The current edition of the compiler has no restrictions on making direct calls to high-level PowerBASIC thread functions, or launching them with CreateThread().

                              What we are trying to do here is give you suitable warning that we are going to be tightening the rules in future versions of PowerBASIC (for specific reasons to do with thread-safe coding), and if you wish to retain source code compatibility, we suggest you convert any CreateThread() calls to high-level PowerBASIC thread functions to CREATE THREAD statements as soon as possible.

                              Thanks!

                              ------------------
                              Lance
                              PowerBASIC Support
                              mailto:[email protected][email protected]</A>
                              Lance
                              mailto:[email protected]

                              Comment


                              • #16
                                The statements by Tom and Lance about possible future restrictions on
                                the use of the CreateThread API also have me concerned. The main
                                reason why I bought the compiler is the access it allows to the Windows
                                API from BASIC.

                                So Lance, I can assume from your last post that I am safe since my programs
                                consist mostly of Windows API calls with a few ANDs, ORs, IF THENs,
                                SELECT CASEs, DO LOOPs thrown in.

                                ------------------
                                Dominic Mitchell
                                Dominic Mitchell
                                Phoenix Visual Designer
                                http://www.phnxthunder.com

                                Comment


                                • #17
                                  Sure!

                                  ------------------
                                  Lance
                                  PowerBASIC Support
                                  mailto:[email protected][email protected]</A>
                                  Lance
                                  mailto:[email protected]

                                  Comment


                                  • #18
                                    What we are trying to do here is give you suitable warning that we are going to be tightening the rules in future versions of PowerBASIC (for specific reasons to do with thread-safe coding), and if you wish to retain source code compatibility, we suggest you convert any CreateThread() calls to high-level PowerBASIC thread functions to CREATE THREAD statements as soon as possible.
                                    Maybe I did not make myself clear.

                                    My concern is with a posting here by Mr. Hanlin three-four weeks ago which suggested the possibilitythat future versions of the compiler would prohibit calling a function which is the object of the THREAD CREATE verb except in that THREAD CREATE statement.

                                    You are now expressing yet another potential restriction: explicit non-support of the CreateThread Win32 API call.

                                    In either case: If such decision has been made, it would be IMO a great disservice to the user community to withhold that information, lest we invest development time in techniques which a new version of the compiler will not not support.


                                    MCM

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

                                    Comment


                                    • #19
                                      Oh dear...

                                      Mr Mattias, please reread my last message and the original discussions. We've revealed nothing more than originally discussed.

                                      Also, by omitting some aspects of my replies in your summary of my post, you imply the changes are likely to be of much wider scope than I have actually described.

                                      Thank you.


                                      ------------------
                                      Lance
                                      PowerBASIC Support
                                      mailto:[email protected][email protected]</A>
                                      Lance
                                      mailto:[email protected]

                                      Comment

                                      Working...
                                      X