所以我有以下代码:
#region Initialize stuff
$files = gci "C:\logs\*.log"
$result = [System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList))
$RunspaceCollection = @()
$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1,5)
$RunspacePool.Open()
$ScriptBlock = {
Param($file, $result)
$content = Get-Content $file.FullName -ReadCount 0
foreach ($line in $content) {
if ($line -match 'A002') {
[void]$result.Add($($line -replace ' +',","))
}}}
#endregion
#region Process Data
Foreach ($file in $files) {
$Powershell = [PowerShell]::Create().AddScript($ScriptBlock).AddArgument($file).AddArgument($result)
$Powershell.RunspacePool = $RunspacePool
[Collections.Arraylist]$RunspaceCollection += New-Object -TypeName PSObject -Property @{
Runspace = $PowerShell.BeginInvoke()
PowerShell = $PowerShell
}}
While($RunspaceCollection) {
Foreach ($Runspace in $RunspaceCollection.ToArray()) {
If ($Runspace.Runspace.IsCompleted) {
[void]$result.Add($Runspace.PowerShell.EndInvoke($Runspace.Runspace))
$Runspace.PowerShell.Dispose()
$RunspaceCollection.Remove($Runspace)
}}}
#endregion
#region Parse Data
$data = ConvertFrom-Csv -InputObject $result -Header "1","2","3","TimeIn","TimeOut","4","5","Dur"
foreach ($line in $data) {
if ($line.TimeIn -match "A002") { $TimeIn += [timespan]::Parse($line.Dur) }
else { $TimeOut += [timespan]::Parse($line.Dur) }}
#endregion
它有效,但我不完全明白如何;)
什么是[System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList))
以及为什么它可以工作,而常规的ArrayList却没有?为什么我需要这个“同步”及其功能?能否请您解释或指点我的一些材料?我似乎找不到任何相关的东西。谢谢!
答案 0 :(得分:1)
为了保证ArrayList的线程安全,所有操作都必须 通过这个包装器来完成。
通过集合枚举本质上不是线程安全的 程序。即使集合是同步的,其他线程也可以 仍然修改集合,这会导致枚举器抛出一个 例外。为了在枚举期间保证线程安全,您可以 要么在整个枚举过程中锁定集合,要么抓住它 由其他线程所做的更改导致的异常。
https://msdn.microsoft.com/en-us/library/3azh197k(v=vs.110).aspx
这是通过谷歌搜索找到的
ArrayList同步方法
了解面向对象脚本/编程的基础知识对您来说是最有益的,因此将来您可以确切地知道要查找的内容。有许多方法可以在PowerShell主机中实现.NET命名空间,类,方法和元素,[System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList))
就是其中之一。