嗨程序员同事们! 希望你知道如何解决我的问题。在写入我的日志文件时,时不总是得到像主题一样的错误。我的解决方案中有3个Windows服务。每个人都使用相同的文件来记录日志。不幸的是我不时得到错误。我的记录器代码如下所示。我使用了synlock,并认为这样就足够了,但有时候不行。你能帮助我改变一下以避免这个问题吗?:
Public NotInheritable Class Logger
Private Shared ReadOnly _locker As New Object()
Public Shared Sub LogIt(ByVal engine As String, ByVal msg As String, ByVal logMessage As String, ByVal Path As String, ByVal IsDebug As Boolean)
If File.Exists(Path) Then
If IsDebug Then
Debug.Print(DateTime.Now & "> " & "| " & engine & " | " & msg & " | " & logMessage)
' Debug.Print(message)
Else
SyncLock _locker
Using w As TextWriter = File.AppendText(Path)
'w.WriteLine(message)
w.WriteLine(DateTime.Now & "> " & "| " & engine & " | " & msg & " | " & logMessage)
w.Flush()
End Using
End SyncLock
End If
Else
If IsDebug Then
' Debug.Print(message)
Debug.Print(DateTime.Now & "> " & "| " & engine & " | " & msg & " | " & logMessage)
Else
SyncLock _locker
Using w As TextWriter = File.CreateText(Path)
' w.WriteLine(message)
w.WriteLine(DateTime.Now & "> " & "| " & engine & " | " & msg & " | " & logMessage)
w.Flush()
End Using
End SyncLock
End If
End If
End Sub
end class
更新:
Imports System.IO
Imports System.Threading
Public NotInheritable Class Logger
Private Shared ReadOnly _locker As New Mutex(False, "Global\AnyHardToGuessName")
Public Shared Sub LogIt(ByVal engine As String, ByVal msg As String, ByVal logMessage As String, ByVal Path As String, ByVal IsDebug As Boolean)
_locker.WaitOne()
Try
If File.Exists(Path) Then
If IsDebug Then
Debug.Print(DateTime.Now & "> " & "| " & engine & " | " & msg & " | " & logMessage)
' Debug.Print(message)
Else
Using w As TextWriter = File.AppendText(Path)
'w.WriteLine(message)
w.WriteLine(DateTime.Now & "> " & "| " & engine & " | " & msg & " | " & logMessage)
w.Flush()
End Using
End If
Else
If IsDebug Then
' Debug.Print(message)
Debug.Print(DateTime.Now & "> " & "| " & engine & " | " & msg & " | " & logMessage)
Else
Using w As TextWriter = File.CreateText(Path)
' w.WriteLine(message)
w.WriteLine(DateTime.Now & "> " & "| " & engine & " | " & msg & " | " & logMessage)
w.Flush()
End Using
End If
End If
Finally
_locker.ReleaseMutex()
End Try
End Sub
End Class
答案 0 :(得分:1)
我的解决方案中有3个Windows服务
产生3个单独的EXE,它们不共享_locker对象。 .NET对象的可见性仅限于创建它们的过程。因此,没有什么能阻止这些程序同时尝试打开日志文件。或者尝试同时创建日志文件,你有一个File.Exists用法的错误,它也必须在SyncLock语句中,以防止两个线程同时检查文件存在时的竞争。
到目前为止,最好的解决方案是让每个EXE使用自己的日志文件,以便_locker对象足够好。如果共享绝对必要,那么您必须使用命名的Mutex来允许这些程序跨进程边界共享同一个同步对象。换句话说:
Private Shared ReadOnly _locker As New Mutex(False, "Global\AnyHardToGuessName")
Public Shared Sub LogIt(...)
_locker.WaitOne()
Try
''...
Finally
_locker.ReleaseMutex()
End Try
End Sub
在源文件的顶部添加Imports System.Threading
。