-1

I have an application that copies files into different directories. As the application is running if I click the BtnExit_Click button nothing happens. I'm only able to exit out of the app after it has run through all the files to copy.

This is my code

Private Sub BtnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click
    BackgroundWorker1.CancelAsync()
    Me.Close()
End Sub

Background Worker:

Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
    Me.txtImgCount.Text = iCount
    Me.txtImgCount.Update()
    Me.fileCount.Text = fCount
    Me.fileCount.Update()
    Me.txtTotal.Update()
    Me.Label8.Text = statusText
    Me.Label8.Update()
    Application.DoEvents()
    Try
        Me.RichTextBox1.Text &= (fileFilename)
        Application.DoEvents()
    Catch ei As DivideByZeroException
        Debug.WriteLine("Exception caught: {0}", ei)
    Finally
    End Try

    Try
        Me.RichTextBox1.Text &= (imgFilename)
        Application.DoEvents()
    Catch ea As DivideByZeroException
        Debug.WriteLine("Exception caught: {0}", ea)
    Finally
    End Try
End Sub

Private Sub BackgroundWorker1_DoWork(sender As Object, e As   System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    RunCopyFiles()
End Sub


 Private Sub RunCopyFiles()
    BackgroundWorker1.WorkerReportsProgress = True

    Dim sFileToFind As String
    Dim location As String
    'Dim File As String
    statusText = "Initiating"
    status = "Initiating..."
    'Directory Files are located in
    location = txtFolderPath.Text
    'Directory ICN files are located in
    imgLocation = txtSearchICN.Text
    'Directory files are to copied into
    MoveLocation = CopyToPath

    createImgFldr = MoveLocation & "\Figures"
    createReportFldr = MoveLocation & "\Reports"
    createXMLFldr = MoveLocation & "\XML files"

    'Create Figures Folder
    If Not IO.Directory.Exists(createImgFldr) Then
        IO.Directory.CreateDirectory(createImgFldr)
        ' MsgBox("folder created" & createFolder)
    End If
    'Create Reports folder
    If Not IO.Directory.Exists(createReportFldr) Then
        IO.Directory.CreateDirectory(createReportFldr)
        'MsgBox("folder created" & createReportFldr)
    End If
    'Create XML folder
    If Not IO.Directory.Exists(createXMLFldr) Then
        IO.Directory.CreateDirectory(createXMLFldr)
        ' MsgBox("folder created" & createFolder)
    End If

    'Text file with list of file names
    Dim filesToCopy = txtFileName.Text
    orphanedFiles = MoveLocation & "\Reports\OrphanedFilesItems.txt"
    ' Create or overwrite the file.
    System.IO.File.Create(orphanedFiles).Dispose()

    ListofGraphics = MoveLocation & "\Reports\ListOfGraphics.txt"
    ' Create or overwrite the file.  
    System.IO.File.Create(ListofGraphics).Dispose()

    Dim removDupBuildLog = MoveLocation & "\Reports\RemvoeDup.txt"
    Dim ListLog = MoveLocation & "\Reports\ListOfGraphics.txt"
    ListofFiles = MoveLocation & "\Reports\ListOfFiles.txt"
    ' Create or overwrite the file.  
    System.IO.File.Create(ListofFiles).Dispose()

    MissingFiles = MoveLocation & "\Reports\MissingGraphicList.txt"
    ' Create or overwrite the file.  
    System.IO.File.Create(MissingFiles).Dispose()
    Dim FILE_NAME As String

    FILE_NAME = txtFileName.Text
    Dim fileNames = System.IO.File.ReadAllLines(FILE_NAME)

    status = "Copying SGML\XML Files"
    statusText = "Copying SGML\XML Files..."
    fCount = 0
    For i = 0 To fileNames.Count() - 1
        Dim fileName = fileNames(i)
        sFileToFind = location & "\" & fileName & "*.*"

        Dim paths = IO.Directory.GetFiles(location, fileName, IO.SearchOption.AllDirectories)
        If Not paths.Any() Then
            System.IO.File.AppendAllText(orphanedFiles, fileName & vbNewLine)
        Else
            For Each pathAndFileName As String In paths
                If System.IO.File.Exists(pathAndFileName) = True Then
                    Dim sRegLast = pathAndFileName.Substring(pathAndFileName.LastIndexOf("\") + 1)
                    Dim toFileLoc = System.IO.Path.Combine(createXMLFldr, sRegLast)
                    Dim moveToFolder = System.IO.Path.Combine(MoveLocation, "XML files", sRegLast)

                    'if toFileLoc = XML file exists move it into the XML files folder
                    If System.IO.File.Exists(toFileLoc) = False Then
                        System.IO.File.Copy(pathAndFileName, moveToFolder)
                        System.IO.File.AppendAllText(ListofFiles, sRegLast & vbNewLine)
                        Application.DoEvents()
                        fileFilename = (fileName) + vbCrLf
                        fCount = fCount + 1
                        'fileCount.Text = fCount
                    End If
                End If
            Next
        End If
        BackgroundWorker1.ReportProgress(100 * (i + 1) / fileNames.Count)
    Next
    CreateGraphicsFunction()
    GetImages()
    Application.UseWaitCursor = False
    Application.DoEvents()
End Sub
HereGoes
  • 1,302
  • 1
  • 9
  • 14
mightymax
  • 431
  • 1
  • 5
  • 16
  • Is your DoWork running a loop? You have to show us. – LarsTech Sep 11 '19 at 15:50
  • The ProgressChanged isn't helpful to us here, but do remove those `Application.DoEvents()` lines. Why would setting the Text property of a RichTextBox cause a DivideByZeroException? Do favor the AppendText method instead. – LarsTech Sep 11 '19 at 16:17
  • You can create a Boolean value that is initially set to false. In the for loop in the `RunCopyFiles` sub, check if that value is true. If it is, exit the loop. In the close Button click event, set the Boolean value to true before calling `backgroundWorker.CancelAsync`. – preciousbetine Sep 11 '19 at 17:37
  • @preciousbetine : The BackgroundWorker has already implemented this via its [`CancellationPending` property](https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.backgroundworker.cancellationpending?view=netframework-4.8#System_ComponentModel_BackgroundWorker_CancellationPending), so no need for an extra variable. Infact all `CancelAsync()` does is change that property, meaning it's up to the programmer to cancel the task by checking it. – Visual Vincent Sep 11 '19 at 19:14

1 Answers1

2

If you look at the code example in the documentation for the BackgroundWorker Class you will see that it checks the worker.CancellationPending property every time through the loop.

So you'll need a couple of changes:

Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
    RunCopyFiles(worker, e)
End Sub
Private Sub RunCopyFiles(worker As BackgroundWorker, e As DoWorkEventArgs)
    ... other code here

    For Each pathAndFileName As String In paths
        ... other code here
        If worker.CancellationPending Then
            e.Cancel = True
            Exit Sub
        End If
    Next

Maybe put another check just after the ReportProgress(...) too.

Also, you will need to set backgroundWorker1.WorkerSupportsCancellation = True.

The Application.UseWaitCursor = False should not be in the worker - put it in the code that calls backgroundWorker1.RunWorkerAsync().

As LarsTech wrote in a comment, you should remove all calls to Application.DoEvents(): problems with it are listed in Use of Application.DoEvents().

Finally, make sure that you are using Option Strict On.

Andrew Morton
  • 24,203
  • 9
  • 60
  • 84