Mutex не блокируется и не использует дескриптор файла - PullRequest
0 голосов
/ 13 июня 2018

У меня проблемы с корректным закрытием дескриптора файла.Я попытался использовать дополнительный Mutex, чтобы гарантировать, что только один поток имеет доступ к этому файлу за один раз.

Насколько я понимаю, конструкция Using должна обеспечивать правильное освобождение дескриптора файла.и Mutex должен гарантировать, что этот код может выполняться только в 1 потоке за раз.

Ошибка возникает, когда регистратор вызывается несколько раз в быстрой последовательности.

Gethashcode былпопытка проверить, совпадает ли экземпляр мьютекса.

Сообщение об ошибке:

Произошло необработанное исключение типа 'System.IO.IOException' в mscorlib.dll
Процесс не может получить доступ к файлу «**** \ LOG.log», поскольку он используется другим процессом.

Источник:

Imports System.IO
Imports System.Net.Mail
Imports System.Threading

Public NotInheritable Class FileLogger
    Private Shared ReadOnly _instance As New Lazy(Of FileLogger)(Function() New FileLogger(), System.Threading.LazyThreadSafetyMode.ExecutionAndPublication)
    Public LOG_LEVEL As Integer = 4
    Public LEVELS As New Dictionary(Of Double, String)
    Private Shared strFile As String = "LOG.log"
    Public Shared FileLoc As New Mutex()

    Public Shared ReadOnly Property getLogger() As FileLogger
        Get
            Return _instance.Value
        End Get
    End Property

    Private Sub New()
        Dim strFile As String = "yourfile.log"
        LEVELS.Add(0, "FATAL   ")
        LEVELS.Add(1, "CRITICAL")
        LEVELS.Add(2, "ERROR   ")
        LEVELS.Add(3, "INFO    ")
        LEVELS.Add(4, "DEBUG   ")
        LEVELS.Add(2.5, "WARNING ")
    End Sub

    Public Sub writeEntry(ByVal message As String, ByVal level As Double)
        If level <= LOG_LEVEL Then
            Dim log_str As String = String.Format("{0} - in: {3} - {1}: {2}", DateTime.Now.ToString, LEVELS(level), message, Thread.CurrentThread.ManagedThreadId)

            Console.WriteLine(log_str)
            If level < 3 Then ' warning or greater write to file else just console
                Console.WriteLine(FileLoc.GetHashCode())
                FileLoc.WaitOne(Timeout.Infinite)
                Using sw As StreamWriter = New StreamWriter(strFile, True) '<-- Debugger points to this line
                    sw.WriteLine(log_str)
                End Using
                FileLoc.ReleaseMutex()
            End If

            If level <= 2 Then 'if error or greater send email
                FileLoc.WaitOne(Timeout.Infinite)
                Dim mail As New MailMessage
                mail.To.Add("email")
                mail.From = New MailAddress("email")
                mail.Subject = "Error on MC Server (SERVERNAME)"
                mail.Body = log_str
                mail.IsBodyHtml = True
                mail.Attachments.Add(New Attachment(strFile))
                Dim smtp As New SmtpClient
                smtp.Host = "IPADDR"
                smtp.Send(mail)
                FileLoc.ReleaseMutex()
            End If
        End If
    End Sub       
End Class

1 Ответ

0 голосов
/ 13 июня 2018

Раздел электронной почты закрывал файл неправильно.оборачивая это в использующую конструкцию исправили проблему.Я также закончил тем, что реализовал конструкцию SyncLock вокруг всей операции.

, так как в некоторых комментариях указывалось, что мьютекс может или не мог делать то, что предполагалось, но дескриптор файла был все ещеоткрыть из операции вложения.

Public Sub writeEntry(ByVal message As String, ByVal level As Double)
        SyncLock FileLoc

            If level <= LOG_LEVEL Then
                Dim log_str As String = String.Format("{0} - in: {3} - {1}: {2}", DateTime.Now.ToString, LEVELS(level), message, Thread.CurrentThread.ManagedThreadId)

                Console.WriteLine(log_str)
                If level < 3 Then ' warning or greater write to file else just console
                    Console.WriteLine(FileLoc.GetHashCode())
                    Using sw As StreamWriter = New StreamWriter(strFile, True)
                        sw.WriteLine(log_str)
                    End Using

                End If

                If level <= 2 Then 'if error or greater send email
                    Using at As Attachment = New Attachment(strFile)
                        Dim mail As New MailMessage
                        mail.To.Add("email")
                        mail.From = New MailAddress("email")
                        mail.Subject = "Error on MC Server (servername)"
                        mail.Body = log_str
                        mail.IsBodyHtml = True

                        mail.Attachments.Add(at)


                        Dim smtp As New SmtpClient
                        smtp.Host = "IPADDR"
                        smtp.Send(mail)
                    End Using


                End If
            End If
        End SyncLock

    End Sub
...