解压缩适用于单线程,但不适用于多线程 [英] Unzipping works on singlethread, but not multithread

查看:649
本文介绍了解压缩适用于单线程,但不适用于多线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用PowerShell解压缩大量文件.我认为这是并行化的好地方.但是,即使它在单线程模式下工作,我进行并行化的尝试似乎也无法使它解压缩.

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?

推荐答案

不确定示例是否复制粘贴,但参数为$ destinationDir,但您引用$ destination,然后使用$ destination创建$ destinationDir.我假设这是一个错字.我修复了您的功能,它可以按预期工作.

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

如果可能的话,我仍然建议从shell.application的comobject转移到使用System.IO.Compression的.Net解决方案.还要注意,PowerShell作业的硬上限为5个同时运行的作业.我不确定这在v5中是否已解决. CookieMonster撰写了优秀文章功能使用基于某些

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.

这篇关于解压缩适用于单线程,但不适用于多线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆