2009-05-08 2 views
0

좋습니다. 일부 배경이 먼저 표시됩니다. 우리는 프로세스 간 리더/라이터 잠금 장치가 필요했습니다. 우리는 파일을 사용하고 LockEx와 UnlockEx를 사용하여 첫 번째 바이트를 잠그기로 결정했습니다. 클래스는 시스템 temp 폴더가 생성 될 때 시스템 temp 폴더에 파일을 만듭니다. 파일은 읽기 쓰기 액세스 및 공유 읽기 | 쓰기 | 삭제로 작성됩니다. 또한 DeleteOnClose를 지정하여 많은 임시 파일을 놓아 두지 않습니다. 분명히 AcquireReader와 AcquireWriter는 적절한 플래그로 LockEx를 호출하고 ReleaseLock은 UnlockEx를 호출합니다.
몇 가지 인스턴스를 실행할 수 있고 완벽하게 작동하는 작은 응용 프로그램을 사용하여이 클래스를 테스트했습니다. 이 응용 프로그램을 사용하는 응용 프로그램에는 문제가 있습니다.이 응용 프로그램은 다른 작은 응용 프로그램에서 다시 생성 할 수 있습니다. 의사 코드에서는프로세스 간 판독기 기록기 잠금 (또는 파일 핸들 및 액세스가 거부 됨)

 
Create InterProcessReaderWriter 
Dispose InterProcessReaderWriter without acquiring any locks 
Launch a child process which takes a reader lock 

처음 실행하면 정상적으로 작동합니다. 다시 실행하려고하면, 처음부터 자식 프로세스가 여전히 잠금을 유지하고있는 동안 파일을 열려고하면 UnauthorisedAccessException이 발생합니다.
공유 권한 위반 문제는 아니지만이 테스트 사례의 모든 프로세스가 동일한 사용자로 실행되고 있습니다. 여기있는 사람 중에 아이디어가 있습니까?

나는 뮤텍스와 세마포어를 사용하여 우리가 원하는 것을 달성 할 것을 제안하는 다른 질문에 주목했습니다. 우리의 구현을 바꿀 수도 있지만 여전히이 문제의 원인을 알고 싶습니다.

답변

0

자식 프로세스가 동일한 파일에 두 번 액세스하려고 시도하는 것처럼 들립니다.

은 고유 한 임시 파일 이름입니까?

+0

동일한 파일에 액세스하려고합니다. 우리는 .ldb 파일로 액세스가 작동하는 것과 비슷한 것을 구현하려고합니다. 그러나 첫 번째 바이트가 아닌 경우 파일 당 하나의 잠금 만 있습니다. – pipTheGeek

0

전체 파일을 잠글 수없는 이유는 무엇입니까? 첫 번째 바이트보다는 오히려. 아래의 샘플 클래스는 단일 시스템으로 제한하지 않고 다른 시스템의 프로세스에서 작동 할 수있는 이점이 있습니다.

다음은 lockfilehelper 클래스를 사용하는 간단한 예입니다.

Module Module1 
    Sub Main() 
     Using lockFile As New LockFileHelper("\\sharedfolder\simplefile.lock") 
      If lockFile.LockAcquire(1000) Then 
       ' Do your work here. 
      Else 
       ' Manage timeouts here. 
      End If 
     End Using 
    End Sub 
End Module 

다음은 Helper 클래스의 코드입니다.

Public Class LockFileHelper 
    Implements IDisposable 
    '------------------------------------------------------------------------------------------------- 
    ' We use lock files in various places in the system to provide a simple co-ordination mechanism 
    ' between different threads within a process and for sharing access to resources with the same 
    ' process running across different machines. 
    '------------------------------------------------------------------------------------------------- 
    Private _lockFileName As String 
    Private _ioStream As IO.FileStream 
    Private _acquiredLock As Boolean = False 
    Private _wasLocked As Boolean = False 
    Public Sub New(ByVal LockFileName As String) 
     _lockFileName = LockFileName 
    End Sub 
    Public ReadOnly Property LockFileName() As String 
     Get 
      Return _lockFileName 
     End Get 
    End Property 
    Public ReadOnly Property WasLocked() As Boolean 
     Get 
      Return _wasLocked 
     End Get 
    End Property 
    Public Function Exists() As Boolean 
     Return IO.File.Exists(_lockFileName) 
    End Function 
    Public Function IsLocked() As Boolean 
     '------------------------------------------------------------------------------------------------- 
     ' If this file already locked? 
     '------------------------------------------------------------------------------------------------- 
     Dim Result As Boolean = False 
     Try 
      _ioStream = IO.File.Open(_lockFileName, IO.FileMode.Create, IO.FileAccess.ReadWrite, IO.FileShare.None) 
      _ioStream.Close() 
     Catch ex As System.IO.IOException 
      ' File is in used by another process. 
      Result = True 
     Catch ex As Exception 
      Throw ex 
     End Try 

     Return Result 
    End Function 
    Public Sub LockAcquireWithException(ByVal TimeOutMilliseconds As Int32) 
     If Not LockAcquire(TimeOutMilliseconds) Then 
      Throw New Exception("Timed out trying to acquire a lock on the file " & _lockFileName) 
     End If 
    End Sub 
    Public Function LockAcquire(ByVal TimeOutMilliseconds As Int32) As Boolean 
     '------------------------------------------------------------------------------------------------- 
     ' See have we already acquired the lock. THis can be useful in situations where we are passing 
     ' locks around to various processes and each process may want to be sure it has acquired the lock. 
     '------------------------------------------------------------------------------------------------- 
     If _acquiredLock Then 
      Return _acquiredLock 
     End If 

     _wasLocked = False 
     Dim StartTicks As Int32 = System.Environment.TickCount 
     Dim TimedOut As Boolean = False 
     If Not IO.Directory.Exists(IO.Path.GetDirectoryName(_lockFileName)) Then 
      IO.Directory.CreateDirectory(IO.Path.GetDirectoryName(_lockFileName)) 
     End If 
     Do 
      Try 
       _ioStream = IO.File.Open(_lockFileName, IO.FileMode.Create, IO.FileAccess.ReadWrite, IO.FileShare.None) 
       _acquiredLock = True 
      Catch ex As System.IO.IOException 
       ' File is in used by another process. 
       _wasLocked = True 
       Threading.Thread.Sleep(100) 
      Catch ex As Exception 
       Throw ex 
      End Try 
      TimedOut = ((System.Environment.TickCount - StartTicks) >= TimeOutMilliseconds) 
     Loop Until _acquiredLock OrElse TimedOut 
     '------------------------------------------------------------------------------------------------- 
     ' Return back the status of the lock acquisition. 
     '------------------------------------------------------------------------------------------------- 
     Return _acquiredLock 
    End Function 
    Public Sub LockRelease() 
     '------------------------------------------------------------------------------------------------- 
     ' Release the lock (if we got it in the first place) 
     '------------------------------------------------------------------------------------------------- 
     If _acquiredLock Then 
      _acquiredLock = False 
      If Not IsNothing(_ioStream) Then 
       _ioStream.Close() 
       _ioStream = Nothing 
      End If 
     End If 
    End Sub 
    Private disposedValue As Boolean = False  ' To detect redundant calls 
    ' IDisposable 
    Protected Overridable Sub Dispose(ByVal disposing As Boolean) 
     If Not Me.disposedValue Then 
      If disposing Then 
       Call LockRelease() 
      End If 

      ' TODO: free shared unmanaged resources 
     End If 
     Me.disposedValue = True 
    End Sub 
#Region " IDisposable Support " 
    ' This code added by Visual Basic to correctly implement the disposable pattern. 
    Public Sub Dispose() Implements IDisposable.Dispose 
     ' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above. 
     Dispose(True) 
     GC.SuppressFinalize(Me) 
    End Sub 
#End Region 
End Class 
+0

우리는 원래 DeleteOnClose를 사용할 수 있기 때문에 원래 파일의 범위를 잠그기 위해갔습니다. 잠금 수준을 변경하기 위해 파일을 닫아야 할 때 어떻게 작동하는지 잘 모르겠습니다. – pipTheGeek

관련 문제