Reputation: 684
I'm creating a program that has auto-backup function, when i tried to copy large or many files in a single folder my application becomes unresponsive/not responding.
I'm using System.IO.File.Copy(source, destination) to copy files.
Below is my code for copying files. I'm also using a progressbar to indicate the file copy process.
Imports System.IO
Public class Form1
Private Sub btnDestPath_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBrowseDestPath.Click
'get destination path from FolderBrowserDialog
Dim destination As String
If (FolderBrowserDialog1.ShowDialog() = Windows.Forms.DialogResult.OK) Then
destination = FolderBrowserDialog1.SelectedPath
txtDestination.Text = destination
End If
End Sub
Private Sub btnCopy_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCopy.Click
'set folder to copy files
Dim sourceFilePath As String = "C:\copyfiles\"
'get destinationpath from txtDestination.Text label
Dim destinationPath As String = txtDestination.Text.Replace(vbCrLf, "")
'add back slash(\) to destinationPath
Dim filepath As String = destinationPath & "\"
'count number of files to copy
Dim filecount As String
filecount = Directory.GetFiles(sourceFilePath).Count
ProgressBar1.Maximum = 1
ProgressBar1.Maximum = filecount 'represent the # of files
ProgressBar1.Step = 1 'step property value of 1 to represent each file being copied
For Each filename As String In Directory.GetFiles(sourceFilePath)
'check if files exist or not
If File.Exists(filename) Then
Dim dFile As String = String.Empty
Dim dFilePath As String = String.Empty
dFile = Path.GetFileName(filename) 'source file filenames
dFilePath = filepath & dFile 'concatenate filepath and filenames
File.Copy(filename, dFilePath, True) 'copy files from "c:\copyfiles" folder to destinationPath
ProgressBar1.PerformStep()
End If
Next
MsgBox("Copy Successful", vbOKOnly, "Message")
End Sub
End Class
Is there anything I can do to improve the code. I hear about using BackgroundWorker would solve the problem, but i don't know where to start. I'm just new to .NET language.
Any help would be great.
Upvotes: 1
Views: 1689
Reputation: 29222
You're on the right track with BackgroundWorker
. You're currently executing your work on the same thread used to respond to your UI. That means that until your file copy finishes, the application is 'too busy' to pay attention to the user clicking on a button or doing anything else.
A BackgroundWorker
executes that method on a different thread, meaning that your UI thread is still available to respond to the user. You might enable them to perform other actions, or you might just have a "cancel" button that allows them to stop the operation.
The documentation and example for BackgroundWorder
are ok. In the example a long-running process is simulated by just having the background thread sleep for a moment. If that happened on the UI thread then the application would freeze, but the application doesn't freeze because it's the BackgroundWorker
thread that's sleeping. The steps are
BackgroundWorker
's DoWork
event. Think of this as the same as putting code in a button's Click
event.myFileCopyBackgroundWorkder.RunWorkerAsync();
. That starts the work happening on a background thread.BackgroundWorker
has progress to report call ReportProgress()
. An event handler in your form can then show the progress to the user.CancelAsync
. As you're looping through the files, check myFileCopyBackgroundWorkder.CancellationPending
to see if the user has requested a cancellation from the main thread. If they have then you can stop.Completed
event so you can indicate that to the user. Or perhaps you disabled certain controls while the process was running (like disabling the "Start" button.) When the process is completed you can re-enable it.Upvotes: 4
Reputation: 1024
Actually it's not a problem.
You've to know that each single process has one worker (the main thread) which is responsible for user interface and user interaction with the program. When you start copying the large file using a synchronous operation like File.Copy()
, this worker (the main thread) is busy copying the file and can't handle events in the UI or do any other operation unless the synchronous operation of copying the file ends, therefore the application UI becomes unresponsive. If you wait the copying process to end (i.e. the synchronous operation ends), the UI will return to a responsive state.
If you want to solve this, you have to use asynchronous operations (which will not block as synchronous operations read more here) or you have to run the synchronous operation on a new single thread or a Task
as suggested here. I recommend using an asynchronous operation.
Upvotes: 1