PowerShell Произошла ошибка при перечислении в коллекции - PullRequest
0 голосов
/ 04 мая 2020

Произошла ошибка при перечислении в коллекции: коллекция была изменена; Операция перечисления может не выполняться

Я читал другие посты о модификации массивов, но у меня нет ошибки при вставке действия удаления. Произошла ошибка при чтении действия во время сбора изменен параллельным процессом (где я использую для l oop). Поэтому я копирую массив, но похоже, что копирование выполняется слишком медленно и прерывается процессом параллельного изменения.

Параллельный процесс делает что-то вроде этого:

$List = [System.Collections.ArrayList]@()
1..100 | %{
    $List.Add([pscustomobject]@{"A"=$_}) | Out-Null
}

Копирует, но прерывает, если коллекция изменена в параллельном процессе

$ListCopy = [System.Collections.ArrayList]@()    
$ListCopy = $List | Select *
$List[0].A = 0

$List[0] # = 0
$ListCopy[0] # = 1

Клон не сделал глубокую копию, оба списка имеют значение 0

$ListCopy = [System.Collections.ArrayList]@()
$ListCopy = $List.Clone()
$List[0].A = 0

$List[0] # = 0
$ListCopy[0] # = 0

Сделайте копию, но это требует много времени

function Clone-Object {
    [Parameter(Mandatory)]
    param(
        $ItemToClone
    )

    $memStream = new-object IO.MemoryStream
    $formatter = new-object Runtime.Serialization.Formatters.Binary.BinaryFormatter
    $formatter.Serialize($memStream,$ItemToClone)
    $memStream.Position=0
    $formatter.Deserialize($memStream)
}

$ListCopy = Clone-Object -ItemToClone $List

$List[0].A = 0

$List[0] # = 0
$ListCopy[0] # = 1

Есть ли какое-либо быстрое решение, как я могу получить доступ к массиву для поиска без прерывания параллельное изменение действий?

Поток 1: собрать значения счетчика производительности и добавить его в ArrayList:

$EndpointMetric += New-UDEndpoint -Schedule $SchedulerMetricQuery -Endpoint {

        #Caches are available in every runsapce
        $MetricConfiguration = $Cache:Configuration.Metric
        $Computername = $Cache:Configuration.Dashboard.Computername

        $Performance= Invoke-PerformanceCounter -Computername $Computername -Countername $MetricConfiguration.Countername

        foreach($PerformanceItem in $Performance){    
            $Cache:Metric.Data.Add((New-MetricItem -Date $PerformanceItem.Date -Computername $PerformanceItem.Computername -Countername $PerformanceItem.Countername -Value ($PerformanceItem.Value))            
        }
}

Поток 2: прочитать ArrayList и оценить данные

Function New-AlertItem{

    Param(
       #Params        
    )

    [nullable[DateTime]]$LastAlertDate = $null

    [pscustomobject]@{
                Date = $Date
                Computername = $Computername.ToUpper()
                Source = $Source
                Event = $Event
                Status = $Status                                
                Summary = $Summary
                Detail = $Detail
                LastAlertDate = $LastAlertDate
                AlertExpirationDate = $Date.AddSeconds($AlertOffset)
                AlertOffset = $AlertOffset
                RepeatAlertOffset = $RepeatAlertOffset
                RepeatAlertByContentChange = $RepeatAlertByContentChange
                MailAlertStatus = $MailAlertStatus
                SmsAlertStatus = $SmsAlertStatus
    }


}

$EndpointAlert += New-UDEndpoint -Schedule $SchedulerAlert -Endpoint {
            $MetricData = $Cache:MetricData.Data | ? Online -eq $True | Select *

        foreach($DataItem in $MetricData){

            #Get most specific (-Last 1) event configuration. Add Ignore to status list because ignore is internal, undocumented status
            $MetricConfigurationItem = $Cache:Configuration.Metric | ? Countername -eq $DataItem.Countername | Select -Last 1            
            if(-not $MetricConfigurationItem){throw "No valid metric configuration found for $DataItem"}

            $Source = "Metric"
            $Summary = """{0}"" is {1}" -f $DataItem.Countername, [math]::Round($DataItem.Value,2)
            $Detail = ""
            $Status = Get-MetricStatus -Value $DataItem.Value

            $AlertConfigurationItem = $Cache:Configuration.Alert | ? {($DataItem.Computername -match $_.Computername) -AND ($Source -match $_.Source) -AND ($DataItem.Countername -match $_.Event) -and (@($_.Status+"Ignore") -contains $Status) -and ($Summary -match $_.Summary) -and ($Detail -match $_.Detail)} | Select -Last 1                
            if(-not $AlertConfigurationItem){throw "No valid alert configuration found for $DataItem"}

            $AlertItem = New-AlertItem `
                    -Date $DataItem.Date `
                    -Computername $DataItem.Computername `
                    -Source $Source `
                    -Event $DataItem.Countername `
                    -Status $Status `
                    -Summary $Summary `
                    -Detail $Detail `
                    -AlertOffset $AlertConfigurationItem.AlertOffset `
                    -RepeatAlertOffset $AlertConfigurationItem.RepeatAlertOffset `
                    -RepeatAlertByContentChange $AlertConfigurationItem.RepeatAlertByContentChange `
                    -MailAlertStatus $AlertConfigurationItem.MailAlertStatus `
                    -SmsAlertStatus $AlertConfigurationItem.SmsAlertStatus

            Send-AlertData -Item $AlertItem

        }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...