来自其中一个system.io类的锁定文件

时间:2017-02-20 22:33:45

标签: vb.net io locking

我正在尝试开发一个简单的批量复制程序,它以指定的时间间隔轮询给定文件夹中的文件。

代码看起来很完美。我的输出提供了一个很好的递归文件列表,但是当我根据列表实际移动它们时,我扫描的每个文件都被锁定。我已经尝试过垃圾收集,处理,在某些点退出潜艇,在某些点进行调试......

请查看我的代码。调用MoveFile时,一切都被锁定。

Imports System
Imports System.IO

Public Structure FileStructure

    Dim Enumerator As Integer
    Dim SPath As String
    Dim DPath As String
    Dim Name As String
    Dim FileSize As Long
    Dim IsFile As Short
    Dim SourceFullName As String
    Dim DestFullName As String

End Structure

Public Class StagingDriveCoordinator

    Dim FilesScanned As FileStructure()
    Dim ScanCount As Integer = -1

    Private Sub ScanAll(ByVal sourcePath As String, ByVal destinationPath As String)

        Dim sourceDirectoryInfo As New System.IO.DirectoryInfo(sourcePath)

        ' ---------------------- Create the appropriate directories --------------------------------
        ' Create source path
        If Not System.IO.Directory.Exists(sourcePath) Then
            System.IO.Directory.CreateDirectory(sourcePath)
        End If

        ' If the destination folder doesn't exist then create it
        If Not System.IO.Directory.Exists(destinationPath) Then
            System.IO.Directory.CreateDirectory(destinationPath)
        End If
        ' ------------------------------------------------------------------------------------------

        Dim AddSize As Integer = 0

        'Figure out how much to resize the array this iteration of ScanAll
        If FilesScanned IsNot Nothing Then
            AddSize = FilesScanned.Count + sourceDirectoryInfo.GetFileSystemInfos.Length
        Else
            AddSize = sourceDirectoryInfo.GetFileSystemInfos.Length
        End If

        'Resize the array
        Array.Resize(FilesScanned, AddSize)

        For Each FileSystemInfo In sourceDirectoryInfo.GetFileSystemInfos

            ScanCount += 1

            FilesScanned(ScanCount).Enumerator = ScanCount
            FilesScanned(ScanCount).SPath = sourcePath.ToString
            FilesScanned(ScanCount).DPath = destinationPath.ToString
            FilesScanned(ScanCount).Name = FileSystemInfo.Name.ToString

            If TypeOf FileSystemInfo Is System.IO.FileInfo Then
                FilesScanned(ScanCount).FileSize = DirectCast(FileSystemInfo, FileInfo).Length
                FilesScanned(ScanCount).IsFile = 1
            Else
                FilesScanned(ScanCount).FileSize = 9223372036854775807
                FilesScanned(ScanCount).IsFile = 0
            End If

            FilesScanned(ScanCount).SourceFullName = System.IO.Path.Combine(sourcePath, FileSystemInfo.Name).ToString
            FilesScanned(ScanCount).DestFullName = System.IO.Path.Combine(sourcePath, FileSystemInfo.Name).ToString

            txtOutput.Text += FilesScanned(ScanCount).Enumerator & vbTab & FilesScanned(ScanCount).SourceFullName & vbNewLine

            If FilesScanned(ScanCount).IsFile = 0 Then
                'Debug
                txtOutput.Text += vbNewLine & "Recursively scanning subfolder " + FilesScanned(ScanCount).Name & "..." + vbNewLine + vbNewLine

                'Recursively call the main scanner.
                ScanAll(FilesScanned(ScanCount).SourceFullName, FilesScanned(ScanCount).DestFullName)

            End If

        Next

    End Sub

    Private Sub MoveFile(ByVal Source, ByVal Destination, ByVal filesize)

        Try

            File.Copy(Source, Destination, True)
            txtOutput.Text += "Moving file... Source: " & Source & ". Filesize: " & filesize.ToString & vbNewLine
            txtOutput.Text += "Destination: " & Destination & vbNewLine & vbNewLine
            File.Delete(Source)

        Catch ex As Exception

            txtOutput.Text += "File " & Source & " is locked." & vbNewLine

        End Try

    End Sub

    Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click

        Select Case cmbPollingFrequency.SelectedItem

            Case "5 Seconds"

                Timer1.Interval = 5000

            Case "30 Seconds"

                Timer1.Interval = 30000

            Case "1 Minute"

                Timer1.Interval = 60000

            Case "5 Minutes"

                Timer1.Interval = 300000

            Case "15 Minutes"

                Timer1.Interval = 900000

            Case "30 Minutes"

                Timer1.Interval = 1800000

            Case "1 Hour"

                Timer1.Interval = 3600000

            Case Else

                MsgBox("You must select an interval.")

        End Select

        Timer1.Start()

    End Sub

    Private Sub TimerTick(sender As Object, e As EventArgs) Handles Timer1.Tick

        Timer1.Stop()

        txtOutput.Text += DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") & vbNewLine
        txtOutput.Text += "Scanning Filesystem..." + vbNewLine + vbNewLine

        'Scan the file system.
        ScanAll(cmbStaging.Text, cmbBackup.Text)


        txtOutput.Text += vbNewLine
        txtOutput.Text += DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") & vbNewLine
        txtOutput.Text += " ------------- Scan cycle completed. --------------- " & vbNewLine & vbNewLine

        txtOutput.Text += "Sorting by filesize..." & vbNewLine & vbNewLine

        ' Sort the file list by size.
        FilesScanned = FilesScanned.OrderBy(Function(x) x.FileSize).ToArray


        txtOutput.Text += "Done." & vbNewLine & vbNewLine
        txtOutput.Text += "Moving smallest files first..." & vbNewLine & vbNewLine



        For Each FileElement In FilesScanned

            If FileElement.IsFile > 0 Then

                'file.FileSize only needed to pass size to text output
                MoveFile(FileElement.SourceFullName, FileElement.DestFullName, FileElement.FileSize)


            End If

        Next

        FilesScanned = Nothing
        ScanCount = -1

        Timer1.Start()

    End Sub

    Private Sub btnStop_Click(sender As Object, e As EventArgs) Handles btnStop.Click

        Timer1.Stop()

    End Sub

End Class

1 个答案:

答案 0 :(得分:0)

我发现了问题。 IO系统没有锁定文件。我试图将其复制到SAME目录......

  

FilesScanned(ScanCount).SourceFullName =   System.IO.Path.Combine(sourcePath,FileSystemInfo.Name).ToString

     

FilesScanned(ScanCount).DestFullName =   System.IO.Path.Combine(sourcePath,FileSystemInfo.Name).ToString

这应该是:

  

FilesScanned(ScanCount).SourceFullName =   System.IO.Path.Combine(sourcePath,FileSystemInfo.Name).ToString

     

FilesScanned(ScanCount).DestFullName =   System.IO.Path.Combine(destinationPath,FileSystemInfo.Name).ToString

一旦我改变它,一切都很完美。