|
-
Apr 16th, 2011, 01:11 PM
#1
Thread Starter
Member
[RESOLVED] Program Keeps Hanging
Hey, everyone! I made a program that backs up data from the My Documents, Favorites, and Desktop folders on Windows XP to a server. When the data is brought down from the server, it brings it down in Windows 7 format. So, for example, the directory to My Documents in Windows XP is "C:\Documents and Settings\username\My Documents." The same directory in Windows 7 is "C:\Users\username\Documents."
Everything works fine in terms of putting files and folders in the correct directory, but when bringing the data down from the server, the program sometimes freezes up and doesn't ever seem to get out of that state. It also makes the computer very slow and unresponsive after a while. Does anyone have any idea why this would occur?
Below, I have a code snippet of my copying code. I include a sleep command and a DoEvents command to halt the thread for a very short duration of time in order to make the UI more responsive.
Code:
Private Sub CopyAllFiles(ByVal Source As String, ByVal Destination As String)
Dim Text As String = vbNullString, FinalPath As String
Dim Dir As DirectoryInfo = New DirectoryInfo(Source), DestDir As DirectoryInfo = New DirectoryInfo(Destination)
Dim DirectoryList() As DirectoryInfo
Dim FileList() As FileInfo
If Not DestDir.Exists() Then
DestDir.Create()
End If
FileList = Dir.GetFiles()
For Each f As FileInfo In FileList
FinalPath = Path.Combine(Destination, f.Name)
' Code that prompts the user to replace the file if it exists already
' If you allow it to replace the file, or if the file doesn't exist, do the following
If CanReplace Then
DisplayText = DisplayText & vbNewLine & "Copying to " & FinalPath & "..."
Call UpdateText()
Try
f.CopyTo(FinalPath, True)
Catch
DisplayText = DisplayText & vbNewLine & "Error copying " & FinalPath & "..."
Call UpdateText()
End Try
System.Threading.Thread.Sleep(100)
Application.DoEvents()
End If
Next
DirectoryList = Dir.GetDirectories()
For Each d As DirectoryInfo In DirectoryList
FinalPath = Path.Combine(Destination, d.Name)
Call CopyAllFiles(d.FullName, FinalPath)
Next
End Sub
The UpdateText Sub is as follows:
Code:
Private Sub UpdateText()
frmDisplay.txtDisplay.Text = DisplayText
frmDisplay.txtDisplay.SelectionStart = frmDisplay.txtDisplay.Text.Length
frmDisplay.txtDisplay.ScrollToCaret()
End Sub
As you can see, it loops a lot, but it works pretty well sometimes. I believe I may have to use some multi-threading to get this to work properly, but I've looked it up and cannot find out how to implement it in my program. Any help would be greatly appreciated!
-
Apr 16th, 2011, 02:24 PM
#2
Fanatic Member
Re: Program Keeps Hanging
Hm yeah for such a resource heavy code you need to have threading to handle the lists. You have to divide your code into two segments that are completely separated from eachother:
- One sub that handles file processing and does not interact with the main form
- A few delegated subs in your Form to use by the thread
Here an example of a delegate to change the progressbar on the main form from inside a thread:
Code:
Delegate Sub myProgressbarAdapter(ByVal percent As Integer)
Private Sub ProgressbarAdapter(ByVal percent As Integer)
If Me.InvokeRequired Then
Dim d As New myProgressbarAdapter(AddressOf ProgressbarAdapter)
Me.Invoke(d, percent)
Else
Progressbar1.Value = percent
End If
End Sub
How to start a new thread:
Code:
Public processfiles As Threading.Thread
Public Sub StartProcess()
processfiles = New System.Threading.Thread(AddressOf FileProcessThread)
processfiles.IsBackground = True
processfiles.Start()
End Sub
Public Sub AbortProcess()
processfiles.Abort()
End Sub
Public Sub FileProcessThread()
'do all non-form related coding here, like copying files
'Me.Text = "Processing" does not work, you need to call a delegate from here
End Sub
So if you want the thread to interact while processing (like a progress), you need to add a delegate for this command to your main form. You call this delegate from inside your thread.
You can also use a "BackGroundWorker", but I like to have all my code close to each other.
-
Apr 16th, 2011, 03:20 PM
#3
Thread Starter
Member
Re: Program Keeps Hanging
Thanks a lot for your help; I really appreciate it! However, it doesn't seem that I'm doing everything correctly. Here's what I added and changed:
Code:
Private Sub CopyAllFiles()
Dim Text As String = vbNullString, FinalPath As String
Dim Dir As DirectoryInfo = New DirectoryInfo(SourcePath), DestDir As DirectoryInfo = New DirectoryInfo(DestPath)
Dim DirectoryList() As DirectoryInfo
Dim FileList() As FileInfo
If Not DestDir.Exists() Then
DestDir.Create()
End If
FileList = Dir.GetFiles()
For Each f As FileInfo In FileList
FinalPath = Path.Combine(Destination, f.Name)
' Code that prompts the user to replace the file if it exists already
' If you allow it to replace the file, or if the file doesn't exist, do the following
If CanReplace Then
DisplayText = DisplayText & vbNewLine & "Copying to " & FinalPath & "..."
Call UpdateText()
Try
f.CopyTo(FinalPath, True)
Catch
DisplayText = DisplayText & vbNewLine & "Error copying " & FinalPath & "..."
Call UpdateText()
End Try
End If
Next
DirectoryList = Dir.GetDirectories()
For Each d As DirectoryInfo In DirectoryList
SourcePath = d.FullName
DestPath = Path.Combine(DestPath, d.Name)
Call CopyAllFiles()
Next
End Sub
I've gotten rid of the parameters for the CopyAllFiles() Sub so that it could work better with the new thread. Instead, I've made the Source path and Destination path private variables. Also, I've added these two Subs:
Code:
Public Sub StartCopy()
NewThread = New System.Threading.Thread(AddressOf CopyAllFiles)
NewThread.IsBackground = True
NewThread.Start()
End Sub
Public Sub StopCopy()
NewThread.Abort()
End Sub
This starts the CopyAllFiles Sub. Now, I've changed my UpdateText Sub and added a Delegate Sub for it, like so:
Code:
Delegate Sub Updater()
Private Sub UpdateText()
If Me.InvokeRequired Then
Dim d As New Updater(AddressOf UpdateText)
Me.Invoke(d)
Else
frmDisplay.txtDisplay.Text = DisplayText
frmDisplay.txtDisplay.SelectionStart = frmDisplay.txtDisplay.Text.Length
frmDisplay.txtDisplay.ScrollToCaret()
End If
End Sub
I got rid of my Sleep and DoEvents commands in the CopyAllFiles Sub because multi-threading would eliminate the need for them, I believe.
As far as the application's functionality as of now, it doesn't work. It goes through everything but actually does not copy the files like it's supposed to.
Could you please let me know if I'm going in the right direction? Thanks!
-
Apr 16th, 2011, 03:56 PM
#4
Fanatic Member
Re: Program Keeps Hanging
Everything seems to be correctly made, and you can copy files from threads since I have done that before as well. 
Maybe this has to be separated:
Code:
Dim Dir As New DirectoryInfo(SourcePath)
Dim DestDir As New DirectoryInfo(DestPath)
And you can leave out the "Call " part before calling a sub, it is left over from vb6 I believe.
It could be the DirectoryInfo class requires form view, in that case use:
Code:
System.IO.Directory.GetDirectories("path")
System.IO.File.Copy("sourcepath", "destpath")
Try replacing DirectoryInfo with these types of functions.
-
Apr 16th, 2011, 06:18 PM
#5
Thread Starter
Member
Re: Program Keeps Hanging
Thanks for the help again, but the program still doesn't copy any of the files. It says that the copying has completed when none of the files got transferred. Is there a way to make a thread execute after another has finished? I've tried using the Background Worker class, but I couldn't understand how to use it. Maybe we should try that. Thanks again!
-
Apr 16th, 2011, 06:23 PM
#6
Fanatic Member
Re: Program Keeps Hanging
Handling finishing of threads is a lot of a hassle. The best method is either having a global variable you can set in the thread to indicate it finished, and/or having a delegate run when the thread finished.
Starting a new thread from a thread is not a very good idea I guess, best is to start a new one from form scope, something with the Thread ID.
And um display the source and dest paths before copying in a msgbox and verify they are correct, you never know.
-
Apr 16th, 2011, 09:03 PM
#7
Thread Starter
Member
Re: Program Keeps Hanging
Hey, bergerkiller! Thanks a lot for the help! I've managed to get my program to multi-thread, finally! It turns out that I wasn't multi-threading the main Sub that triggered the CopyAllFiles Sub. Now I have three threads: One for copying, one for updating the text on the screen, and one for showing forms (otherwise I'd get an error that the main thread is supposed to handle showing them). This works very, very well, and the program no longer hangs, even when copying over 9 GB of data! I just have to fix up some of the visual aspects of it because some forms don't pop up as they're supposed to.
Also, I'd like to mention that I used DirectoryInfo and FileInfo, and they do work with a thread that isn't the main thread. Below is an example of what I did for the text updating thread:
Code:
Public TextThread As Threading.Thread
Public Sub TextUpdate()
TextThread = New Threading.Thread(AddressOf UpdateText)
TextThread.Start()
End Sub
Public Sub UpdateText()
frmDisplay.txtDisplay.Text = DisplayText
frmDisplay.txtDisplay.SelectionStart = frmDisplay.txtDisplay.Text.Length
frmDisplay.txtDisplay.ScrollToCaret()
TextThread.Abort()
End Sub
I also decided to put most of my Subs in a separate Module as opposed to on the main form itself. This allowed me to utilize global variables and make my life easier. 
Thanks again!
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|