为什么不锁定整个文件?而不是第一个字节。下面的示例类的好处是它可以跨不同机器上的进程工作,而不是将其限制在一台机器上。
这是一个使用下面的 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