I need to read a logfile in two different applications at the same time. As PB internal functions do not allow to set the Share-Mode I am using direct API-Calls. There I am using #FILE_SHARE_READ, but the second call always fails with error-code 32: ERROR_SHARING_VIOLATION: - The process cannot access the file because it is being used by another process.
Below is an example with 3 threads where one writes a logfile and two try to read them line by line. Does anyone know why the second read-thread fails? It should be possible to read the same file at the same time several times without problems.
When the writer-thread opens the file in modes #FILE_SHARE_WRITE or #FILE_SHARE_READ | #FILE_SHARE_WRITE the file can not be read by any of the two threads only when #FILE_SHARE_READ is used for the writer-thread and then it only works if the reader-threads use #FILE_SHARE_WRITE or #FILE_SHARE_READ | #FILE_SHARE_WRITE, not when using #FILE_SHARE_READ. Strange ...
Thanks
Code: Select all
XIncludeFile "File.pbi" ; https://pb-source-repositery.googlecode.com/svn/trunk/CodeArchiv_v4-Beta/WindowsAPI-Examples/FileHandling_WinAPI.pb
Declare API_FileCreateShared2(*File.API_FileHandle,File$)
Declare API_FileReadShared2(*File.API_FileHandle,File$)
Declare.s ShowError()
OpenConsole()
Global file.s = "test.txt"
Procedure WriteMe(number)
Protected handle.API_FileHandle
PrintN("Starting Thread " + Str(number))
If API_FileCreateShared2(handle,file)
For i=1 To 40
API_WriteStringN(handle,Str(i))
PrintN("Thread " + Str(number) + ": " + Str(i))
Delay(500)
Next
Else
PrintN("Thread " + Str(number) + ": Can Not write To file: " + ShowError())
EndIf
EndProcedure
Procedure ReadMe(number)
Protected handle.API_FileHandle
PrintN("Starting Thread " + Str(number))
If API_FileReadShared2(handle,file)
While API_EOF(handle)=#False
line.s = API_ReadString(handle)
PrintN("Thread " + Str(number) + ": " + line.s)
Delay(1000)
Wend
API_CloseFile(handle)
Else
PrintN("Thread " + Str(number) + ": Unable to open file: " + ShowError())
EndIf
EndProcedure
CreateThread(@WriteMe(), 0)
Delay(1000)
CreateThread(@ReadMe(), 1)
CreateThread(@ReadMe(), 2)
Delay(20000)
Procedure API_FileCreateShared2(*File.API_FileHandle,File$)
;*File\FHandle=CreateFile_(File$,#GENERIC_WRITE,#FILE_SHARE_READ Or #FILE_SHARE_WRITE,0,#CREATE_ALWAYS,#FILE_ATTRIBUTE_NORMAL,0)
*File\FHandle=CreateFile_(File$,#GENERIC_WRITE,#FILE_SHARE_READ,0,#CREATE_ALWAYS,#FILE_ATTRIBUTE_NORMAL,0)
;*File\FHandle=CreateFile_(File$,#GENERIC_WRITE,#FILE_SHARE_WRITE,0,#CREATE_ALWAYS,#FILE_ATTRIBUTE_NORMAL,0)
If *File\FHandle=#INVALID_HANDLE_VALUE
ProcedureReturn #False
Else
ProcedureReturn #True
EndIf
EndProcedure
Procedure API_FileReadShared2(*File.API_FileHandle,File$)
*File\FHandle=CreateFile_(File$,#GENERIC_READ,#FILE_SHARE_READ Or #FILE_SHARE_WRITE,0,#OPEN_EXISTING,#FILE_ATTRIBUTE_NORMAL,0)
;*File\FHandle=CreateFile_(File$,#GENERIC_READ,#FILE_SHARE_READ,0,#OPEN_EXISTING,#FILE_ATTRIBUTE_NORMAL,0)
;*File\FHandle=CreateFile_(File$,#GENERIC_READ,#FILE_SHARE_WRITE,0,#OPEN_EXISTING,#FILE_ATTRIBUTE_NORMAL,0)
If *File\FHandle=#INVALID_HANDLE_VALUE
ProcedureReturn #False
Else
*File\Buffer=GlobalAlloc_(#GMEM_FIXED|#GMEM_ZEROINIT,#API_File_BufferLen)
*File\ReadPos=*File\Buffer
*File\DataInBuffer=0
ProcedureReturn #True
EndIf
EndProcedure
Procedure.s ShowError()
Protected Error,*MemoryID,e$,Length
Error = GetLastError_()
If Error
*MemoryID = AllocateMemory(255)
If *MemoryID
Length = FormatMessage_ (#FORMAT_MESSAGE_FROM_SYSTEM, #Null, Error, 0, *MemoryID, 255, #Null)
If Length > 1 ; Some error messages are "" + Chr (13) + Chr (10)... stoopid M$... :(
e$ = PeekS(*MemoryID, Length - 2) + " (" + StrU(Error.i) + ")"
Else
e$ = "Unknown error!"
EndIf
FreeMemory(*MemoryID)
ProcedureReturn e$
Else
ProcedureReturn "Error while decoding Error("+Str(Error)+")"
EndIf
Else
ProcedureReturn "No error has occurred!"
EndIf
EndProcedure