【问题标题】:Writing To Text File, File In Use By Another Process, Multithreaded Application .NET写入文本文件,文件被另一个进程使用,多线程应用程序 .NET
【发布时间】:2015-01-14 23:39:19
【问题描述】:

下午,

我有一个程序,我确实需要保留某种日志来确定程序在做什么。本质上,该软件会监控桌面上的一个窗口,以实时暂停我们的通话记录服务器上的通话记录。

让我们争论一下,通话记录本身是由监控代理提取的,他们说对话的某个敏感部分已经被记录下来,而实际上它应该被静音,如果他们说代理没有完成他们的工作并单击暂停录制按钮或未发生 onfocus 操作我会遇到需要证明软件同时在做什么的情况。

我决定将软件的操作写入存储在用户应用数据中的 .txt 文件中。

这在大多数情况下都有效,但是即使 .txt 从未被任何其他程序访问,我也会时不时地得到“此文件正在被另一个进程使用”。

此应用程序是多线程的,并且确实会非常频繁地调用写入日志,我正在使用以下代码:

Private Sub WriteToLog(ByVal strSubTitle As String, ByVal strLogInfo As String)

    Try
        If My.Computer.FileSystem.FileExists(strLogFilePath) = True Then

            'Delete yesterdays log file
            Dim strFileDate As Date = File.GetCreationTime(strLogFilePath)
            strFileDate = FormatDateTime(strFileDate, DateFormat.ShortDate)

            'If strFileDate < Date.Today Then
            '    My.Computer.FileSystem.DeleteFile(strLogFilePath)
            'End If

            Using outFile As IO.StreamWriter = My.Computer.FileSystem.OpenTextFileWriter(strLogFilePath, True)

                outFile.WriteLine("" & Date.Today & "," & Date.Now.ToLongTimeString & ", " & strUsername & ", " & strSubTitle & ", " & Replace(strLogInfo, ",", "|") & "")
                outFile.Close()

            End Using
            ''CSV File
            'outFile.WriteLine("" & Date.Today & "," & Date.Now.ToLongTimeString & ", " & strUsername & ", " & strSubTitle & ", " & Replace(strLogInfo, ",", "|") & "")
            'outFile.Close()

        Else

            Using outFile As IO.StreamWriter = My.Computer.FileSystem.OpenTextFileWriter(strLogFilePath, False)

                outFile.WriteLine("" & Date.Today & "," & Date.Now.ToLongTimeString & ", " & strUsername & ", " & strSubTitle & ", " & Replace(strLogInfo, ",", "|") & "")
                outFile.Close()

            End Using
            'CSV File
            'outFile.WriteLine("Date, Time, Username, Sub(Process), Information")
            'outFile.WriteLine("" & Date.Today & "," & Date.Now.ToLongTimeString & ", " & strUsername & ", " & strSubTitle & ", " & Replace(strLogInfo, ",", "|") & "")
            'outFile.Close()

        End If

    Catch ex As Exception
        CreateErrorFile(ex.Message, ex.StackTrace, "Log Write Failure!")
    End Try

End Sub

是否有人可以说明为什么这会说另一个进程正在使用该文件。

我猜当两个单独的线程尝试执行 'WriteToLog' Sub 而一个或另一个正在写入文件时会发生这种情况。

我在正确的轨道上吗?如果是这样,我该如何纠正?

干杯,

詹姆斯

【问题讨论】:

标签: vb.net multithreading


【解决方案1】:

您要么希望通过使用辅助线程中的Invoke 方法来调用主线程上的写入功能,从而使只有一个线程能够写入日志文件,要么您可以使用 .NET 的各种同步机制之一。

这是第一种方法的简单示例:

Private Sub BackgroundMethod()
    'do stuff
    Me.Invoke(New Action(Of String)(AddressOf WriteToLog), "write a line blah blah")
    'do more stuff
End Sub

Private Sub WriteToLog(valueToWrite As String)
    System.IO.File.AppendAllLines(MyLogFilePath, {valueToWrite})
End Sub

这是一个使用 SyncLock 块的示例:

Private lock As New Object()

Private Sub BackgroundMethod()
    'do stuff
    WriteToLog("write a line blah blah")
    'do more stuff
End Sub

Private Sub WriteToLog(valueToWrite As String)
    SyncLock (lock)
        System.IO.File.AppendAllLines(MyLogFilePath, {valueToWrite})
    End SyncLock
End Sub

MSDN 有很好的同步机制信息:http://msdn.microsoft.com/en-us/library/ms228964%28v=vs.110%29.aspx

【讨论】:

    【解决方案2】:

    我会使用一个全局队列来添加新条目,如果日志写入器不忙,则启动它以写下所有可用行。

    类似的东西:

      Private LogList As New Queue(Of String)
      Private WriterBusy As Boolean = False
    
      Private Sub WriteToLog(ByVal strSubTitle As String, ByVal strLogInfo As String)
    
        LogList.Enqueue("" & Date.Today & "," & Date.Now.ToLongTimeString & ", " & strUsername & ", " & strSubTitle & ", " & Replace(strLogInfo, ",", "|") & "")
    
        If WriterBusy = True Then Exit Sub
        WriterBusy = True
    
        Try
            If My.Computer.FileSystem.FileExists(strLogFilePath) = True Then
            ...
    
            Using outFile As IO.StreamWriter = My.Computer.FileSystem.OpenTextFileWriter(strLogFilePath, True)
    
              While LogList.Count > 0 
                  outFile.WriteLine(LogList.Dequeue)
              End While
              outFile.Close()
    
            End Using
            ...
        End Try
    
        WriterBusy = False
    
      End Sub
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-03
      • 1970-01-01
      • 1970-01-01
      • 2015-11-26
      • 1970-01-01
      • 2016-04-27
      • 1970-01-01
      相关资源
      最近更新 更多