PDA

Click to See Complete Forum and Search --> : [RESOLVED] Duplicate methods, would like to know how to prevent


~*McoreD*~
Dec 6th, 2005, 12:10 AM
Hey Guys,

The Project: TreeGUI, I am currently coding has a Windows Service and a GUI. Both do the same job so I have about 99% of the code shared. There is only one method I don't know how to share with both Windows.Service project and Windows.Form project.

Here is the code in the Windows.Form

Private Sub IndexNowTreeNetLib(ByVal myReader As cReader)

Dim where As String

Dim folderList As New ArrayList
folderList = myReader.GetConfig.FolderList
Dim treeNetLib As New cTreeNetLib(myReader)

Select Case mIndexMode

Case cReader.IndexingMode.INDEX_FILE_IN_EACH_DIR

For i As Integer = 0 To myReader.GetConfig.FolderList.Count - 1
Dim strDirPath As String = myReader.GetConfig.FolderList.Item(i)
where = strDirPath + "\" + myReader.GetConfig.GetIndexFileName
Try
Dim sw As New StreamWriter(where, False)
Select Case myReader.GetConfig.IndexFileExtension
Case Is = ".html"
'MessageBox.Show(myReader.GetConfig.mCssFilePath)
treeNetLib.mBooFirstIndexFile = True
treeNetLib.IndexFolderToHtml(strDirPath, sw, True)
Case Else
treeNetLib.IndexFolderToTxt(strDirPath, sw, True)
End Select
sw.Close()
If myReader.GetConfig.ZipFilesInEachDir Then
myReader.ZipAdminFile(where)
End If
bwIndexer.ReportProgress(0.0, strDirPath)
Catch ex As System.UnauthorizedAccessException
End Try
Next

Case cReader.IndexingMode.INDEX_FILE_IN_ONE_FOLDER

If myReader.GetConfig.isMergeFiles Then

where = myReader.GetConfig.GetIndexFilePath

Dim sw As New StreamWriter(where, False)

If myReader.GetConfig.FolderList.Count > 1 Then
For i As Integer = 0 To myReader.GetConfig.FolderList.Count - 2
Dim strDirPath As String = myReader.GetConfig.FolderList.Item(i)
Dim dir As New cDir(strDirPath)
Select Case myReader.GetConfig.IndexFileExtension
Case Is = ".html"
treeNetLib.mBooMoreFilesToCome = True
treeNetLib.IndexFolderToHtml(strDirPath, sw, False)
Case Else
treeNetLib.IndexFolderToTxt(strDirPath, sw, False)
End Select
bwIndexer.ReportProgress(0.0, strDirPath)
Next
End If

Dim lastDir As New cDir(myReader.GetConfig.FolderList.Item(myReader.GetConfig.FolderList.Count - 1))
Select Case myReader.GetConfig.IndexFileExtension
Case Is = ".html"
treeNetLib.mBooFirstIndexFile = False
treeNetLib.IndexFolderToHtml(lastDir.GetDirPath, sw, True)
Case Else
treeNetLib.IndexFolderToTxt(lastDir.GetDirPath, sw, True)
End Select
sw.Close()
If myReader.GetConfig.ZipMergedFile Then
myReader.ZipAdminFile(where)
End If

bwIndexer.ReportProgress(0.0, lastDir.GetDirPath)
End If

End Select

End Sub


And here is the code for in the Windows.Service:

Private Sub IndexNowTreeNetLib(ByVal myReader As cReader)

Dim where As String

Dim folderList As New ArrayList
folderList = myReader.GetConfig.FolderList
Dim treeNetLib As New cTreeNetLib(myReader)

Select Case mIndexMode

Case cReader.IndexingMode.INDEX_FILE_IN_EACH_DIR

For i As Integer = 0 To myReader.GetConfig.FolderList.Count - 1
Dim strDirPath As String = myReader.GetConfig.FolderList.Item(i)
where = strDirPath + "\" + myReader.GetConfig.GetIndexFileName
Try
Dim sw As New StreamWriter(where, False)
Select Case myReader.GetConfig.IndexFileExtension
Case Is = ".html"
'MessageBox.Show(myReader.GetConfig.mCssFilePath)
treeNetLib.mBooFirstIndexFile = True
treeNetLib.IndexFolderToHtml(strDirPath, sw, True)
Case Else
treeNetLib.IndexFolderToTxt(strDirPath, sw, True)
End Select
sw.Close()
If myReader.GetConfig.ZipFilesInEachDir Then
myReader.ZipAdminFile(where)
End If
Catch ex As System.UnauthorizedAccessException
End Try
Next

Case cReader.IndexingMode.INDEX_FILE_IN_ONE_FOLDER

If myReader.GetConfig.isMergeFiles Then

where = myReader.GetConfig.GetIndexFilePath

Dim sw As New StreamWriter(where, False)

If myReader.GetConfig.FolderList.Count > 1 Then
For i As Integer = 0 To myReader.GetConfig.FolderList.Count - 2
Dim strDirPath As String = myReader.GetConfig.FolderList.Item(i)
Dim dir As New cDir(strDirPath)
Select Case myReader.GetConfig.IndexFileExtension
Case Is = ".html"
treeNetLib.mBooMoreFilesToCome = True
treeNetLib.IndexFolderToHtml(strDirPath, sw, False)
Case Else
treeNetLib.IndexFolderToTxt(strDirPath, sw, False)
End Select
Next
End If

Dim lastDir As New cDir(myReader.GetConfig.FolderList.Item(myReader.GetConfig.FolderList.Count - 1))
Select Case myReader.GetConfig.IndexFileExtension
Case Is = ".html"
treeNetLib.mBooFirstIndexFile = False
treeNetLib.IndexFolderToHtml(lastDir.GetDirPath, sw, True)
Case Else
treeNetLib.IndexFolderToTxt(lastDir.GetDirPath, sw, True)
End Select
sw.Close()
If myReader.GetConfig.ZipMergedFile Then
myReader.ZipAdminFile(where)
End If

End If

End Select

End Sub


As you now see, both methods are indentical, but the only difference in Windows.Forms method is that it reports Progress to a ProgressBar.

I can't seperate the method from the Form because it won't then report the progress to the ProgressBar in the Windows.Form.

Well, this is what the project is all about: http://microsoftuse.temp.powweb.com/mcored/downloads/treegui/

I hope you understand my problem. Is there any workground for this?

Thanks in advance.
McoreD

conipto
Dec 6th, 2005, 05:39 AM
YOu could put the method in a class, with a structure similar to this:



Public Class myIndexer

Private Percent_complete As Integer
Public Property Percent As Integer 'Or whatever type you need it to be
Get
return Percent_complete
End Get
Set (Value)
Percent_complete = value
End Set
End Property
Public Sub IndexNow(ByVal myReader as cReader)
'Implementation the same as yours
'Except that instead of the report progress method, something is done
'to the percent_complete variable
End Sub
End Class


And then compile the class to a DLL and put it in the Global Assembly Cache, and call the percent property at some interval from within your forms application. This would enable you to in the future optimize or work on just one version of the program which could be accessed from both versions.

Bill

~*McoreD*~
Dec 6th, 2005, 07:06 AM
That's an excellent idea, thanks conipto. :)

Let me focus on one For Each loop:

For i As Integer = 0 To myReader.GetConfig.FolderList.Count - 1
Dim strDirPath As String = myReader.GetConfig.FolderList.Item(i)
where = strDirPath + "\" + myReader.GetConfig.GetIndexFileName
Try
Dim sw As New StreamWriter(where, False)
Select Case myReader.GetConfig.IndexFileExtension
Case Is = ".html"
'MessageBox.Show(myReader.GetConfig.mCssFilePath)
treeNetLib.mBooFirstIndexFile = True
treeNetLib.IndexFolderToHtml(strDirPath, sw, True)
Case Else
treeNetLib.IndexFolderToTxt(strDirPath, sw, True)
End Select
sw.Close()
If myReader.GetConfig.ZipFilesInEachDir Then
myReader.ZipAdminFile(where)
End If
bwIndexer.ReportProgress(0.0, strDirPath)
Catch ex As System.UnauthorizedAccessException
End Try
Next

In this Loop, say when FolderList.Count = 6, ProgressBar will increment upto 6. In other words, ReportProgress method is called 6 times. But when the Function is outside of the Form, you can only call the Function once, and get the ReportProgress value once. So to fix that proble, like you said, we have to call the PercentageDone variable from time to time. I suppose this is done via a Timer, say every 100 milliseconds etc? If Timer is a solution then I am in the right track thanks to you.

Cheers,
McoreD

conipto
Dec 6th, 2005, 09:23 PM
Or, you could be even cooler, and raise an event each time it is incremented.

Something like this in your DLL class:

For i As Integer = 0 To myReader.GetConfig.FolderList.Count - 1
Dim strDirPath As String = myReader.GetConfig.FolderList.Item(i)
where = strDirPath + "\" + myReader.GetConfig.GetIndexFileName
Try
Dim sw As New StreamWriter(where, False)
Select Case myReader.GetConfig.IndexFileExtension
Case Is = ".html"
'MessageBox.Show(myReader.GetConfig.mCssFilePath)
treeNetLib.mBooFirstIndexFile = True
treeNetLib.IndexFolderToHtml(strDirPath, sw, True)
Case Else
treeNetLib.IndexFolderToTxt(strDirPath, sw, True)
End Select
sw.Close()
If myReader.GetConfig.ZipFilesInEachDir Then
myReader.ZipAdminFile(where)
End If
percent +=1
'bwIndexer.ReportProgress(0.0, strDirPath)
RaiseEvent (PercentChanged, New EventArgs)
Catch ex As System.UnauthorizedAccessException
End Try
Next

'and outside of your update method but still within the class for the updater
Public Event PercentChanged(ByVal ea As EventArgs)'Adding the eventargs is really just if you want to add more functionality to the event, so optional.


'Then from within your form or service, dim the class variable withevents,
Dim WithEvents myupdaterClass as new UpdaterClass

'and add a sub to handle the percent changed event
Private Sub MyPercChangedSub(byval e as EventArgs) Handles myupdaterClass.PercentChanged
'Update your progress bar based on the percent property
End Sub


That's a nice clean way to do it in my opinion, that doesn't waste timer checks when for example progress hasn't been made. I know it's minor, but this IS Code it Better, right :) Though, I'm sure someone will disagree with it, but that's the beauty of this forum ;)

Bill

~*McoreD*~
Dec 6th, 2005, 11:17 PM
This is very cool conipto. I was just about to post a reply thanking you and to say how Timer worked well. However for operations that took less than 100 milliseconds, ProgressBar did not uptdate accurately (left at 0). So RaiseEvents will be a cool way to do it.

Thanks again,
McoreD

~*McoreD*~
Dec 6th, 2005, 11:36 PM
(Not related to the Thread but...) Looks like there is a limitation in VB according to my design.

Derived classes cannot raise base class events

http://msdn2.microsoft.com/en-us/library/0ecakwbz.aspx

TreeLib and TreeNetLib are two indexing Engines which inherits TreeEngine.

An event can be raised only from the declaration space in which it is declared. Therefore, a class cannot raise events from any other class, even one from which it is derived.

Error ID: BC30029
To correct this error

Move the Event statement or the RaiseEvent statement so they are in the same class.

I might need to do that and change some other code accordingly.

~*McoreD*~
Dec 7th, 2005, 12:13 AM
Unfortunately this Multithreading error hit in the middle:

Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on.

Though I cannot implement it to this project, I learnt a lot from you about EventArgs and am able implement it to any other single threaded project. So thank you again conipto, for your excellent ideas.

Cheers,
McoreD