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