Произошла ошибка при перечислении в коллекции: коллекция была изменена; Операция перечисления может не выполняться
Я читал другие посты о модификации массивов, но у меня нет ошибки при вставке действия удаления. Произошла ошибка при чтении действия во время сбора изменен параллельным процессом (где я использую для 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
}
}