Announcement

Collapse
No announcement yet.

Simultaneously write file

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

  • Simultaneously write file

    File "Teste.txt" would save 60 regs. (20 each thread).
    What is wrong in this code ?
    Thanks

    Code:
    #COMPILE EXE
    
    FUNCTION PBMAIN () AS LONG
    
    LOCAL x AS LONG
    LOCAL s AS LONG
    
    DIM idThread(10) AS LONG
    
    FOR x = 1 TO 3
    
      THREAD CREATE MyThread(x) TO idThread(x)
      SLEEP 0
    
    NEXT
    
    MSGBOX "3 Threads Started!" & $CRLF & "Wait for them to finish!"
    
    DO
      FOR x = 1 TO 3
        THREAD STATUS idThread(x) TO s
        IF s THEN ITERATE DO
      NEXT
    LOOP WHILE s
    
    MSGBOX "Finished!"
    
    
    END FUNCTION
    
    FUNCTION MyThread (BYVAL x AS LONG) AS LONG
    
    LOCAL n AS LONG
    LOCAL t AS SINGLE
    
    hF&=FREEFILE
    ERRCLEAR
    OPEN "TESTE.txt" FOR OUTPUT LOCK SHARED AS #hF&
    IF ERR THEN MSGBOX STR$(ERR)
    
    FOR n = 1 TO 20
      
      PRINT #hF&, FORMAT$(n,"00")+" "+STR$(x)
     
    NEXT n
    
    MSGBOX "end : " & STR$(x) 
    
    END FUNCTION
    Last edited by Paulo Ferreira; 17 Nov 2007, 01:01 PM. Reason: .

  • #2
    Try this:

    Code:
    DO 
     hF&=FREEFILE
     ERRCLEAR
     OPEN "TESTE.txt" FOR APPEND LOCK SHARED AS #hF&
     IF ERR THEN SLEEP 256
    LOOP UNTIL ISFALSE(ERR)
    Last edited by Elias Montoya; 17 Nov 2007, 02:27 PM.

    Comment


    • #3
      If you open the file for output, it will get overwritten by each thread. Open the file in APPEND mode...
      Regards,
      Peter

      "Simplicity is a prerequisite for reliability"

      Comment


      • #4
        True.

        Comment


        • #5
          Peter may be totally or partially correct. It depends on whether this file needs to continually grow or start anew each time. The code below starts anew with the first thread, so may want a slight delay in starting the threads:
          Code:
          FUNCTION MyThread (BYVAL x AS LONG) AS LONG
              LOCAL n AS LONG
              LOCAL t AS SINGLE
              LOCAL hF AS LONG
              LOCAL a$
              hF&=FREEFILE
              IF x = 1 THEN
                  OPEN "TESTE.txt" FOR OUTPUT LOCK SHARED AS #hF&
                  IF ERR THEN
                      ? STR$(ERR)
                      EXIT FUNCTION
                  END IF
              ELSE
                  OPEN "TESTE.txt" FOR APPEND LOCK SHARED AS #hF&
                  IF ERR THEN
                      ? STR$(ERR)
                      EXIT FUNCTION
                  END IF
              END IF
              FOR n = 1 TO 20
                PRINT #hF&,FORMAT$(n,"00")+" "+STR$(x)
              NEXT n
              CLOSE #hF&
              ? "end : " & STR$(x)
          END FUNCTION
          Rick Angell

          Comment


          • #6
            In the first post you read: "File "Teste.txt" would save 60 regs. (20 each thread)."
            So it needs appending.

            [edit]
            Richard,
            Your example won't work in all cases. (Because it's not assured that thread #1 will run as first one...)
            [/edit]
            Last edited by Peter Lameijn; 17 Nov 2007, 02:39 PM.
            Regards,
            Peter

            "Simplicity is a prerequisite for reliability"

            Comment


            • #7
              Ok. Thanks friends.
              So, you say me that "simultaneous" write is not possible.
              I have to wait the end of a process and so start other to write access.
              Is it ?

              Comment


              • #8
                No, but every time you open the file for output, the previous contents gets lost because it is overwritten. Just open the file for append, or open the file only once for output in PbMain() before starting the threads, and close the file if the threeads are closed...
                Code:
                #COMPILE EXE
                
                GLOBAL hf AS LONG
                
                FUNCTION PBMAIN () AS LONG
                
                LOCAL x AS LONG
                LOCAL s AS LONG
                
                DIM idThread(10) AS LONG
                
                hF&=FREEFILE
                ERRCLEAR
                OPEN "TESTE.txt" FOR OUTPUT LOCK SHARED AS #hF&
                IF ERR THEN MSGBOX STR$(ERR)
                
                FOR x = 1 TO 3
                
                  THREAD CREATE MyThread(x) TO idThread(x)
                  SLEEP 0
                
                NEXT
                
                MSGBOX "3 Threads Started!" & $CRLF & "Wait for them to finish!"
                
                DO
                  FOR x = 1 TO 3
                    THREAD STATUS idThread(x) TO s
                    IF s THEN ITERATE DO
                  NEXT
                LOOP WHILE s
                
                CLOSE #hf&
                
                MSGBOX "Finished!"
                
                END FUNCTION
                
                FUNCTION MyThread (BYVAL x AS LONG) AS LONG
                
                LOCAL n AS LONG
                LOCAL t AS SINGLE
                
                FOR n = 1 TO 20
                  
                  PRINT #hF&, FORMAT$(n,"00")+" "+STR$(x)
                 
                NEXT n
                
                MSGBOX "end : " & STR$(x) 
                
                END FUNCTION
                Last edited by Peter Lameijn; 17 Nov 2007, 06:03 PM.
                Regards,
                Peter

                "Simplicity is a prerequisite for reliability"

                Comment


                • #9
                  It makes no sense to do these writes in a separate thread of execution. But let's just say this is a demo, where the ordinary rules don't apply... in that case....

                  You'd want to use a critical section as a synchronization object. (q.v. in your WinApi reference or in at least two thousand six hundred forty-one places here).
                  Michael Mattias
                  Tal Systems (retired)
                  Port Washington WI USA
                  [email protected]
                  http://www.talsystems.com

                  Comment


                  • #10
                    Richard,
                    Your example won't work in all cases. (Because it's not assured that thread #1 will run as first one...)
                    Yes, so I suggested a delay before starting the other threads, yet even at 60 x 3, no observed problems. Yet the example is *not* real world. But I agree, Peter, that doing an OPEN or KILL in the MAIN should effecively begin a new file as well, then start the threads.

                    Your code does not do that however, and the threads do not know the handle as it is not passed to them. Setting it global does not work either. In fact each thread wants it's file handle for APPEND, otherwise nothing gets written to the file.

                    I suppose if one wants to have threads monitoring separate 'ports" that you want to grab the data from and file in one file maybe the situation might be real world, but as Michael correctly points out that would need for a critcal section approach (to avoid lost data). You can easily simulate such by introducing random delays in each thread before a write. Some data gets to the file, some does not.
                    Rick Angell

                    Comment


                    • #11
                      I changed the code for hf to be a global long, that will work. (You don't need separate handles in the threads, because they share the global vars)
                      I can imagine that it's used for logging some data on several threads running to handle user requests. (I use a similar thing with a voice response system serving 60 lines on an ISDN system with equal threads, all logging to a shared logfile)
                      Regards,
                      Peter

                      "Simplicity is a prerequisite for reliability"

                      Comment


                      • #12
                        Well, in a real application, I need that 2 programs write in the same
                        file at same time.
                        The threads were a simulation in fact.
                        Like propose P.Lameijn, open "Teste.txt" previously, then all threads
                        writes at the file "simultaneously".
                        Well, if a program open a file, and other program (or dll) need to write
                        in this file, I want to know the file handle.
                        I can get the file open status.
                        Do I get file handle with its name ?

                        Comment


                        • #13
                          In a DLL used by the program, you can just pass the handle to the DLL.
                          In another executable you cannot use the same handle, because they don't share the same memory space...
                          Using several threads is something completely different from using several executables. You cannot use the threaded example to simulate multiple executables...
                          Regards,
                          Peter

                          "Simplicity is a prerequisite for reliability"

                          Comment


                          • #14
                            Well, in a real application, I need that 2 programs write in the same file at same time.
                            The threads were a simulation in fact.
                            Two threads of the same process do not in any way simulate two processes writing to the same file.

                            For data integrity issues involved in multi-user programming, here's an article and a little code you can download from my website:



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

                            Comment


                            • #15
                              In another executable you cannot use the same handle, because they don't share the same memory space...
                              You would not want to use the same handle (although you actually could do that by passing a duplicated handle, but that is esoteric by anyone's standards).

                              Any "handle" of any type is always specific to and valid only in the process in which it was obtained or for which it was duplicated.

                              Not quite on topic but.....

                              You know a long time ago I wrote an MS-DOS demo to test/review file status in the shared/locked file environment. You could do things like select what file to open in what mode with what locking and sharing , then lock / free individual records and try writing, reading, etc and query the status codes and data.

                              I wonder if maybe something like this for Windows - using two separate processes - might not be a handy thing? It could allow 'network testing' without having two computers.

                              (Since MS-DOS was single-tasking only, the only way the old tool was really useful was to run two separate copies of the program on two seprate computers and have each computer open the same network file).

                              Maybe this is another possibility for one of Mr. Purvis' contests? Surely it could be useful to "newbies to multiuser programming."

                              MCM
                              Last edited by Michael Mattias; 18 Nov 2007, 10:51 AM.
                              Michael Mattias
                              Tal Systems (retired)
                              Port Washington WI USA
                              [email protected]
                              http://www.talsystems.com

                              Comment

                              Working...
                              X