Powershell-并行和线程安全使用?

Powershell-并行和线程安全使用?,powershell,Powershell,6个小时后,我越来越近了。开始学习Visual Studio代码vs ISE,因此我可以轻松使用PowerShell 7。了解了-Parallel,然后了解了如何在不使用$using:的情况下调用脚本块中的变量。(这花了很长时间!)尝试了Asjob部分,但这似乎不适合这个部分。我基本上是一个20行的文本文件,并在一个300k+行的CSV中搜索匹配项 我相信我已经找到了一个我无法理解的部分。我想我需要知道如何根据错误使用“线程安全”对象 $textfile = "C:\test_delete\ke

6个小时后,我越来越近了。开始学习Visual Studio代码vs ISE,因此我可以轻松使用PowerShell 7。了解了-Parallel,然后了解了如何在不使用$using:的情况下调用脚本块中的变量。(这花了很长时间!)尝试了Asjob部分,但这似乎不适合这个部分。我基本上是一个20行的文本文件,并在一个300k+行的CSV中搜索匹配项

我相信我已经找到了一个我无法理解的部分。我想我需要知道如何根据错误使用“线程安全”对象

$textfile = "C:\test_delete\key_words.txt"
$loglocation = "C:\test_delete\datablob.csv"
$outputfile = "C:\test_delete\test5.csv"

New-Item -Path $outputfile

Get-Content $textfile | ForEach-Object -Parallel {
    Select-String  -Raw -Path $using:loglocation -Pattern $_ |
    Out-File -append $using:outputfile
}
错误 输出文件: 线| 3 | Out File-使用:outputfile追加$ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |进程无法访问文件“C:\test\u delete\test5.csv”,因为其他进程正在使用该文件

在ForEach对象帮助(示例11)中,它讨论了线程安全的用法,示例声明了变量=线程安全语法。这是有道理的。除此之外,我希望最终为$outfile声明一个参数,这将需要以安全的方式调用。我已经超越了自己,但就是不知道如何对$outfile进行线程安全调用


抱歉说得太冗长了,这是我的第一篇帖子,我只是想转告一下,我花了一些时间试图得到这个。提前谢谢

这里是我的首选选项-不要对每个对象使用
并行
这里,它是不必要的

Select-String -Path $loglocation -Pattern (Get-Content $textfile) | Out-File $outputfile -Append
就这样,您完成了,无需担心并发写访问:)


如果您仍然坚持,下面是几个如何处理这个特定示例的示例

帮助文件中的“线程安全”字典分配之所以有效,是因为所讨论的数据类型(
ConcurrentDictionary
)是在考虑线程安全的情况下实现的

如果要以线程安全的方式写入文件,则需要手动维护锁或互斥锁:

$fileLock = [System.Threading.ReaderWriterLockSlim]::new()

Get-Content $textfile | ForEach-Object -Parallel {
    $lock = $using:fileLock
    try{
        $lock.EnterWriteLock()
        Select-String  -Raw -Path $using:loglocation -Pattern $_ |
        Out-File -append $using:outputfile
    }
    finally{
        if($lock.IsWriteLockHeld){
            $lock.ExitWriteLock()
        }
    }
}
或者,将写操作移到并行循环之外:

Get-Content $textfile | ForEach-Object -Parallel {
    Select-String  -Raw -Path $using:loglocation -Pattern $_
} | Out-File -append $using:outputfile

你有没有想过你正在编码的详细步骤?看起来你是。。。[A] 将文本文件的一行发送到管道。[B] 加载整个CSV并搜索该行[共20行]。加载文件20次![C] 将任何匹配项发送到输出文件中。//将目标文件加载一次,然后将该文件与整个“匹配这些”行集进行比较,这不是更有意义吗?
Get Content
cmdlet有一个
-ReadCount
参数,您可以告诉它通过管道以块的形式发送内容。。。[咧嘴笑]我从没想过发一行短信。那是个好主意。我没有想到这一点。但我当前的错误是写入输出。问题是从不同线程写入同一文件。能否将| out文件放在foreach之外?@Berry-输出问题是由于将文件访问放在管道内部引起的。相反,将管道输出分配给$Var&使用它在事后进行写入操作。//如果您的结果对于可用的RAM来说太大,您可以使用互斥的思想来查看线程安全的文件访问。谢谢Mathias!我感谢您花时间提供解决方案,即使您觉得额外的努力不值得。我最终使用了你的第二个备选方案,我不得不编辑它并从文件行中删除$using。由于一些搜索的规模,我曾希望看到并行搜索是否会缩短搜索时间。使用use-Process平均需要2分钟57秒,使用您的解决方案将时间缩短到85秒!再次感谢!我需要学习更多关于系统线程的知识。嗯,到目前为止,这个项目有点失败。而搜索-并行vs-进程显然更快。使用“findstr”进行并行测试…findstr更快:(@Berry尝试将
-SimpleMatch
添加到
选择字符串中