【问题标题】:Filestream read only locking PC文件流只读锁定 PC
【发布时间】:2016-09-13 04:36:51
【问题描述】:

我正在尝试读取 LAN 上远程 PC 上的 Windows 更新日志。大多数时候我可以成功读取文件,但有时程序会锁定。可能是由于一个或另一个问题 - 并不重要。我需要的是一种在 Filestream/Streamreader 锁定时恢复的方法——我不确定是哪个导致了锁定。一些流可以设置超时,但下面的文件流在调用 .CanTimeout 时返回 False。

如果流被锁定,我该如何突破? (有时锁很紧,需要断电才能恢复。)

有没有办法在我实际尝试读取之前测试流是否会失败?

是否有其他方法可以读取另一个程序已打开的远程日志文件? (我正在使用流方法,因为常规 File.IO 被阻止,因为文件在远程 PC 上打开。)


我越来越接近(我认为)这段代码。我浏览了引用帖子中的 pathExists 代码,但它是 OP 而不是答案。

Imports System.IO
Import System.Threading
...
Function GetAULog(PCName As String) As String
    Try
        Dim sLogPath As String = String.Format("\\{0}\c$\Windows\SoftwareDistribution\ReportingEvents.log", PCName)
        If PCName = My.Computer.Name Then
            sLogPath = String.Format("C:\Windows\SoftwareDistribution\ReportingEvents.log", PCName)
        End If
        ' read file open by another process
        If Not pathExists(sLogPath) Then
            MsgBox("AU log file not found - PC on?")
            Return "NA"
        End If
        Using fs As New FileStream(sLogPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
            Using sr As New StreamReader(fs)
                Dim s As String = sr.ReadToEnd
                Return s
            End Using
        End Using
    Catch ex As Exception
        MsgBox(ex.Message)
        Return ""
    End Try
End Function

Public Function pathExists(path As String) As Boolean
    Dim exists As Boolean = True
    Dim t As New Thread(New ThreadStart(Sub() exists = System.IO.File.Exists(path)))
    t.Start()
    Dim completed As Boolean = t.Join(500)
    'half a sec of timeout
    If Not completed Then
        exists = False
        t.Abort()
    End If
    t = Nothing
    Return exists
End Function

至少在 PC 关闭时 pathExists() 代码会在短时间内返回 False。

我现在的问题是程序退出时进程没有结束 - 至少在 IDE 中,没有检查运行时。

我添加了t = Nothing,但这并没有帮助。我无法弄清楚正确的 Using 语法来测试它。 线程超时后如何正确清理?

【问题讨论】:

    标签: vb.net multithreading filestream streamreader


    【解决方案1】:

    我遇到过这种锁定直到重启问题的情况。这似乎是由 tcpip 自动调整功能引起的。您可以通过运行来解决此问题

    netsh interface tcp set global autotuninglevel=disable
    

    如果您有访问权限,请在两台机器上运行它。我通过检查锁等尝试了一些解决这个问题的方法,但我可以解决它的唯一方法是禁用它。问题不在于锁定,而在于文件共享协议中的较低级别。

    See this article for more detail

    【讨论】:

    • 这可能不是我的问题,因为文件(如果存在)(我需要更改代码以检查存在)大小合理。它似乎在连接时挂起。也许 Exists 会暴露连接问题并希望超时。
    • 当我遇到问题时,不管是大文件还是小文件。我们使用脚本将 .net 应用程序推送到 30 台不同的机器上。在重新启动完成之前,这些机器中的一些会间歇性地锁定文件共享。用上面提到的这个方法修复它。
    • 我并不能很好地访问目标机器,所以我需要更通用的解决方案。
    【解决方案2】:

    “最终”代码如下所示。发生超时时不会触发异常,因此.Abort 显然没问题。

    当超时确实发生时,由于远程 PC 没有响应,有一个进程挂起,大约 30 秒后消失。我在使用 IDE 时注意到这一点,我运行程序并测试关闭的 PC。如果我然后退出程序,表单会关闭,但 IDE 会挂起约 30 秒 - 此时我可以单击停止调试并且它可以工作,但 IDE 在约 30 秒超时后会自行继续。

    我猜 Final 块中的 t = Nothing 不会释放线程。 t.Dispose 不存在。

    所以,除了最终自行清除的悬空线程外,一切正常。程序不再挂到无法停止的地步。

    'Imports System.IO
    'Imports System.Threading
    Public Function pathExists(path As String) As Boolean
        ' check for file exists on remote PC
        Dim exists As Boolean = False
        Dim t As New Thread(New ThreadStart(Sub() exists = System.IO.File.Exists(path)))
        Try
            t.Start()
            Dim completed As Boolean = t.Join(500)
            'half a sec of timeout
            If Not completed Then
                exists = False
                t.Abort()
            End If
        Catch ex2 As ThreadInterruptedException
            MsgBox("timeout on AU log exists test" & vbNewLine & ex2.Message,, "ThreadInterruptedException")
        Catch exAbort As ThreadAbortException
            MsgBox("timeout on AU log exists test" & vbNewLine & exAbort.Message,, "ThreadAbortException")
        Catch ex As Exception
            MsgBox("exception on AU log exists test" & vbNewLine & ex.Message)
        Finally
            t = Nothing
        End Try
        Return exists
    End Function
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-19
      • 2018-05-28
      • 1970-01-01
      相关资源
      最近更新 更多