So I have some code which copies files to 5 remote PCs on the network. I have a class which impersonates the methods who logon is required
''' <summary>
''' Returns the names of the files including their path that match the regex pattern found in this directory.
''' </summary>
''' <param name="searchOption">
''' The parameter option SearchOption.AllDirectories indicates that the search should include the current directory and any subdirectories
''' The parameter option SearchOption.TopDirectoryOnly indicates that the search should only include the current directory.
''' </param>
Public Function GetFileContent(filePath As String, searchPattern As String, Optional searchOption As SearchOption = Nothing) As String() Implements IEPMADirectoryAccess.GetFileContent
If searchOption = Nothing Then
searchOption = SearchOption.TopDirectoryOnly
End If
LogonUser(UserName, Domain, Password, LogonType.LOGON32_LOGON_NEW_CREDENTIALS, 0, UserToken)
Using WindowsIdentity.Impersonate(UserToken)
Return Directory.GetFiles(filePath, searchPattern, searchOption)
End Using
End Function
''' <summary>
''' Get the name of the Ward from the directory of the current file path
''' </summary>
Public Function GetWardName(filePath As String) As String Implements IEPMADirectoryAccess.GetWardName
LogonUser(UserName, Domain, Password, LogonType.LOGON32_LOGON_NEW_CREDENTIALS, 0, UserToken)
Using WindowsIdentity.Impersonate(UserToken)
Return New DirectoryInfo(Path.GetDirectoryName(filePath)).Name
End Using
End Function
''' <summary>
''' Creates a directory for the given path
''' </summary>
Public Sub CreateDirectory(directoryPath As String) Implements IEPMADirectoryAccess.CreateDirectory
LogonUser(UserName, Domain, Password, LogonType.LOGON32_LOGON_NEW_CREDENTIALS, 0, UserToken)
Using WindowsIdentity.Impersonate(UserToken)
Directory.CreateDirectory(directoryPath)
End Using
End Sub
''' <summary>
''' Deletes a file from the specified path
''' </summary>
Public Sub DeleteFile(filePath As String) Implements IEPMADirectoryAccess.DeleteFile
LogonUser(UserName, Domain, Password, LogonType.LOGON32_LOGON_NEW_CREDENTIALS, 0, UserToken)
Using WindowsIdentity.Impersonate(UserToken)
File.Delete(filePath)
End Using
End Sub
''' <summary>
''' Copies a file from the source path to the destination path
''' </summary>
Public Sub CopyFile(sourceFilePath As String, destFilePath As String, overwrite As Boolean) Implements IEPMADirectoryAccess.CopyFile
LogonUser(UserName, Domain, Password, LogonType.LOGON32_LOGON_NEW_CREDENTIALS, 0, UserToken)
Using WindowsIdentity.Impersonate(UserToken)
File.Copy(sourceFilePath, destFilePath, overwrite)
End Using
End Sub
part of the code in the parallel loop looks like this:
'If PC is switched on
If IsOnline(device.PCName) Then
'For each PC of the ward, get the corresponding folder path
targetPath = "\\" + device.PCName + "\c$Report P\"
'Requires access to the network share
If Not Directory.Exists(targetPath) Then
DirectoryAccess.CreateDirectory(targetPath)
End If
'Requires access to the network share
For Each fileName As String In DirectoryAccess.GetFileContent(targetPath, "*.pdf")
'Purge (Delete) previous versions of this file in the destination folder
Dim fileConst As String
fileConst = arr(1)
If fileName.Contains(fileConst) Then
'Requires access to the network share
DirectoryAccess.DeleteFile(fileName)
End If
Next
DirectoryAccess.CopyFile(f, Path.Combine(targetPath, Path.GetFileName(f), True)
End If
In the main module I am timing the difference in copying the files when using a normal for loop compared to a parallel for loop but with the same code content within the for loops:
Initially, the parallel copying is 18 seconds but then becomes 2.82 seconds for the second run.
The third run is 1.81 seconds.
I have checked that the using blocks for impersonation have correctly disposed and reverted to my original credentials after exiting the using block. I am not sure why it is slow in the first run but then speeds up? Could it be that initially the four PCs are inactive, so the process of copying activates them but takes longer?
I have an IsOnline function that checks if the PCs are powered on, if not I just skip them to ensure it doesn't slow down the process.
Turns out it was slow because time was measured on different number of pcs on at any one time. Some PCs went to sleep during the measurement so affected the processing time