Announcement

Collapse
No announcement yet.

GUI freezes when writing to non-existent UNC folder

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

  • GUI freezes when writing to non-existent UNC folder

    Hi all,

    I currently have this problem.
    I have 2 pc's connected in a local network, running Windows XP Pro SP3.
    My program runs on one of these pc's and it needs to write a file in a shared directory on the other pc.
    It uses a UNC name to create the file, like "\\pc2\shared\file.txt" .
    Everything fine. Except ... when the 2nd pc is turned off or not connected to the network.
    In that case, my program cannot create the file. Not a real problem, except that while Windows is searching and trying to connect to the missing pc, my dialog (GUI) freezes....
    If the OPEN FOR OUTPUT command (or the GETATTR command for that matter) times out, control is again returned to my dialog and it unfreezes.

    So, I figured I would solve this by putting the file writing code in a separate thread.
    No deal ... Even when trying to create that file from within a thread, my dialog still freezes....

    I have attached a small demo that shows the problem. If you want to test, make sure you use a UNC name that does not exist on your local network.

    So basically I just want to verify if a UNC folder exists or not.
    Any suggestions?
    I am using PBWin 9.x

    Kind regards
    Eddy
    Code:
    #COMPILE EXE
    #DIM ALL
    
    '------------------------------------------------------------------------------
    '   ** Includes **
    '------------------------------------------------------------------------------
    #IF NOT %DEF(%WINAPI)
        #INCLUDE "WIN32API.INC"
    #ENDIF
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Constants **
    '------------------------------------------------------------------------------
    %IDD_DIALOG1   =  101
    %IDC_LABEL1    = 1001
    %IDC_TEXTBOX1  = 1002
    %IDC_BUTT_EXIT = 1003
    %IDC_TIMER     = 2000
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Declarations **
    '------------------------------------------------------------------------------
    DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
    DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
    
    GLOBAL ghMain AS LONG
    
    '------------------------------------------------------------------------------
    DECLARE SUB DEBUG (st$)
    $ConClose = "$CON:CLOSE"
    
    SUB DEBUG (st$)
        STATIC Hwnd&
        LOCAL szConsole AS ASCIIZ * 255
        IF Hwnd& = 0 THEN
           ALLOCCONSOLE
           SETCONSOLETITLE "PBDLL Console"
           Hwnd& = GETSTDHANDLE(%STD_OUTPUT_HANDLE)
           SETCONSOLETEXTATTRIBUTE Hwnd&, %FOREGROUND_RED OR _
                                          %FOREGROUND_GREEN OR _
                                          %FOREGROUND_BLUE
        END IF
        IF Hwnd& > 0 THEN
           ' a magic word that close console
           IF st$=$ConClose THEN
              FREECONSOLE
              Hwnd& = 0
              EXIT SUB
           END IF
           szConsole = st$ & $CRLF
           WRITECONSOLE Hwnd&,szConsole,LEN(szConsole),%NULL,%NULL
        END IF
    END SUB
    
    '------------------------------------------------------------------------------
    FUNCTION PBMAIN()
        ShowDIALOG1 %HWND_DESKTOP
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    CALLBACK FUNCTION ShowDIALOG1Proc()
        LOCAL dThread AS DWORD
        LOCAL lResult AS LONG
        
        SELECT CASE AS LONG CBMSG
            CASE %WM_INITDIALOG
                SETTIMER ghMain, %IDC_TIMER, 2000, BYVAL %NULL 
    
            CASE %WM_TIMER
                SELECT CASE CBWPARAM
                    CASE %IDC_TIMER
                            'Start the thread that tries to connect to the network pc
                        THREAD CREATE TestThread(0) TO dThread
                        THREAD CLOSE dThread TO lResult
    
                END SELECT
    
            CASE %WM_COMMAND
                SELECT CASE AS LONG CBCTL
                    CASE %IDC_BUTT_EXIT
                        IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                            DIALOG END ghMain
                        END IF
    
                END SELECT
        END SELECT
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
        LOCAL lRslt AS LONG
    
        LOCAL hDlg  AS DWORD
    
        DIALOG NEW hParent, "Dialog1", 0, 0, 284, 137, %WS_POPUP OR _
            %WS_BORDER OR %WS_DLGFRAME OR %WS_CAPTION OR %WS_SYSMENU OR _
            %WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX OR %WS_CLIPSIBLINGS OR _
            %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
            %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR _
            %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
        CONTROL ADD LABEL,   hDlg, %IDC_LABEL1, "Start typing some text when console appears... or click " + _
            "Exit button ...", 11, 5, 265, 20
        CONTROL ADD TEXTBOX, hDlg, %IDC_TEXTBOX1, "", 10, 25, 265, 65, %WS_CHILD _
            OR %WS_VISIBLE OR %WS_TABSTOP OR %ES_LEFT OR %ES_MULTILINE OR _
            %ES_AUTOHSCROLL OR %ES_AUTOVSCROLL OR %ES_WANTRETURN, %WS_EX_CLIENTEDGE OR %WS_EX_LEFT _
            OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR
        CONTROL ADD BUTTON,  hDlg, %IDC_BUTT_EXIT, "Exit", 10, 100, 95, 30
        
        ghMain = hDlg
        DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
    
        FUNCTION = lRslt
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    THREAD FUNCTION TestThread(BYVAL lDummy AS LONG) AS LONG
        LOCAL j, ff AS LONG
        STATIC ThreadRunning AS LONG
        
        IF ThreadRunning THEN 
            debug "Thread already running"
            EXIT FUNCTION
        ELSE
            debug "Starting thread. GUI freezes if directory not found..."    
        END IF    
        ThreadRunning = 1
    
        'Either GETATTR or OPEN FOR OUTPUT freeze the dialog
            
        'j = GETATTR("\\pc2\shared\")  '<----- Make sure this is a non-existent directory to show problem
    
        ff = FREEFILE
        OPEN "\\pc2\shared\test.txt" FOR OUTPUT LOCK SHARED AS #ff  '<----- Make sure this file does not exist to show problem
            IF NOT ERR THEN PRINT #ff, "......."
        CLOSE #ff
    
        IF ERRCLEAR THEN
            debug "Directory not found.....!!"
        ELSE
            debug "Directory found."
        END IF
        
        ThreadRunning = 0            
    END FUNCTION
    '------------------------------------------------------------------------------
    Eddy

  • #2
    >OUTPUT LOCK SHARED

    That makes no sense, you can't share a file which you have opened for output. This may be causing something funky to happen.


    Valid Folder?
    Code:
    IF DIR$("\\computername\sharename[\folder]", ONLY %SUBDIR) = "" THEN 
       Message "Oops invalid output folder" 
    ELSE
        do your thing
    ....
    May not work on root directory. Come to think if it, GETATTR may not either.

    Your dialog should NOT be 'freezing' the way you coded it.

    If not solved later I'll try program.

    MCM
    Last edited by Michael Mattias; 16 Sep 2009, 09:53 AM.
    Michael Mattias
    Tal Systems Inc. (retired)
    Racine WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      you can't share a file which you have opened for output
      No reason why not, as far as I know. It would have limited application, but might be useful for allowing another application to retrieve at least partial results while you're processing.

      Comment


      • #4
        Hi Eddy,

        I know you are not using Microsoft Office but it sounds similar to a problem I encountered a while ago.

        Microsoft Support Article ID: 313937

        The program stops responding when you try to open or to save a file in an Office 2002 program, in an Office 2003 program and in an Office 2007 program
        The article can be found at...

        http://support.microsoft.com/kb/313937

        Hopefully you'll find something relevant in there.

        Best Regards,

        David
        Last edited by David Warner; 16 Sep 2009, 11:55 AM.

        Comment


        • #5
          No reason why not, as far as I know. It would have limited application, but might be useful for allowing another application to retrieve at least partial results while you're processing.
          But if the file is new ("OPEN FOR OUTPUT" , it does not yet have a directory entry, meaning no other program can find it.

          I think that's right.

          I mean you might...
          Code:
           OPEN xxxx FOR OUTPUT   as hFile
           CLOSE    hFile    
           ' file now exists empty and has an entry in the directory (except on NT4?) 
           OPEN  xxxx FOR APPEND   ACCESS READ WRITE LOCK SHARED ......
          That might work.
          Michael Mattias
          Tal Systems Inc. (retired)
          Racine WI USA
          [email protected]
          http://www.talsystems.com

          Comment


          • #6
            David,
            Yes, the symptoms described by MS are simular to what I see. The program basically freezes while trying to connect to a (non-existent) network folder.
            The solutions they propose are ... well ... "MS solutions" :laugh:

            Michael,
            Simply opening and closing the file, without writing data, shows the same behaviour. Which is to be expected. The delay is caused by Windows searching for the (missing) network folder.
            The big mistery is that this delay also seems to halt the main dlgproc, causing the dialog/window to freeze.

            Kind regards
            Eddy

            Comment


            • #7
              PB function GETATTR and API function GETFILEATTRIBUTES can be used to detect the existence of a folder.

              On my home network, PB function GETATTR shows the freezing behaviour mentioned below.
              The API function GETFILEATTRIBUTES does not show the behaviour.
              I will do some more testing on another network tomorrow.

              Kind regards
              Eddy

              Comment


              • #8
                >The article can be found at...

                Excellent link, thank you.

                It explains why I get some delays when I don't have my laptop turned on and logged in to my network.

                Nice work, Redmond!

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

                Comment

                Working...
                X