2017-02-20 34 views
0

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

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

Пожалуйста, взгляните на мой код. Когда вызывается 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 
+0

Вы действительно не знаете, в чем проблема, потому что вы не изучаете исключение. «Заблокированное» сообщение об ошибке - это ваш ответ на все. – Plutonix

+0

Я думаю, что вы не можете переместить файл, потому что у него есть итератор списка. Как правило, вы не можете изменять список, пока вы его просматриваете. – leetibbett

+0

@leetibbett: Боюсь, что это не так. Вы правы в том, что вы не можете изменять тип коллекции, когда в цикле 'Для каждого', но он никогда не модифицирует сам массив, поэтому нет проблем с тем, что он сейчас делает в цикле. –

ответ

0

Я нашел проблему. Система IO НЕ блокировала файл. Я пытался скопировать его в тот же каталог ...

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

Как только я сменил его, все сработало отлично.