问题
I'm trying to unzip a ton of files using PowerShell. I figured this is a great place to parallelize. However, my attempt to parallelize seems to make the unzip have no effect, even though it worked in the single threaded mode.
$unzip = {
param([string]$sourceFile, [string]$destinationDir)
#Clean out the destination if it exists
rmdir $destination -Force -Recurse -ErrorAction SilentlyContinue
mkdir $destination -Force
#Actual unzip
$shell = new-object -com shell.application
$zipFile = $shell.NameSpace($sourceFile)
$destinationDir = $shell.NameSpace($destination)
$destinationDir.copyhere($zipFile.items())
}
foreach($file in $files){
$args = ($file.FullName, $destinationDir)
Start-Job $unzip -ArgumentList $args
}
#Cleanup
While (Get-Job -State "Running") { Start-Sleep 2 }
Remove-Job *
When I run this without the multithreaded code, it works fine, but with it none of the files actually get unzipped. Why is this?
回答1:
Not sure if your sample is copy pasted or not, but your param is $destinationDir but you reference $destination and then use $destination to create $destinationDir. I'm assuming this is a typo. I fixed your function and it works as you would expect.
$unzip = {
param([string]$sourceFile, [string]$destination)
#Clean out the destination if it exists
rmdir $destination -Force -Recurse -ErrorAction SilentlyContinue
mkdir $destination -Force
#Actual unzip
$shell = new-object -com shell.application
$zipFile = $shell.NameSpace($sourceFile)
$destinationDir = $shell.NameSpace($destination)
$destinationDir.copyhere($zipFile.items())
}
Using receive-job would have shown you the following errors pointing you in the right direction:
Cannot bind argument to parameter 'Path' because it is null.
+ CategoryInfo : InvalidData: (:) [mkdir], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,mkdir
+ PSComputerName : localhost
Method invocation failed because [System.String] doesn't contain a method named 'copyhere'.
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
+ PSComputerName : localhost
I would still recommend moving away from the comobject for shell.application and to a .Net solution using System.IO.Compression if possible however. Also note that powershell jobs have a hard cap of 5 concurrently running jobs. I'm not sure if this is fixed in v5 or not. CookieMonster wrote an excellent post and a function using runspaces based off some work by Boe Prox as a better way of handling concurrency with improved performance.
来源:https://stackoverflow.com/questions/28509659/unzipping-works-on-singlethread-but-not-multithread