многопоточность с пробелами вместо цикла foreach - PullRequest
0 голосов
/ 08 июля 2019

У меня есть скрипт с циклом foreach. Он имеет около дюжины функций, каждая из которых собирает информацию с общего ресурса C $ удаленных машин (обрезка текстовых файлов, проверка версии файла и т. Д.)

Это, однако, занимает некоторое время, так как данные каждой машины собираются по порядку. (иногда он работает с вводом 500+)

Хотелось бы поместить это в пространства выполнения с параллельным выполнением, но пока никаких примеров не получилось. Я совершенно новичок в этой концепции.

Схема текущего скрипта $ inputfile = c: \ temp \ computerlist.txt

функция 1 функция 2 функция 3 и т. д.

цикл foreach функция 1 функция 2 функция 3

Все результаты записаны на экран с помощью write-host на данный момент.

Ответы [ 2 ]

0 голосов
/ 08 июля 2019

Это будет одновременно и будет выполняться примерно за 10 секунд.Компьютер может быть localhost три раза, если он работает.

invoke-command comp1,comp2,comp3 { sleep 10; 'done' } 

Простая попытка API (потоков):

$a =  [PowerShell]::Create().AddScript{sleep 5;'a done'}
$b =  [PowerShell]::Create().AddScript{sleep 5;'b done'}
$c =  [PowerShell]::Create().AddScript{sleep 5;'c done'}
$r1 = $a.BeginInvoke(); $r2 = $b.BeginInvoke() $r3 = $c.BeginInvoke()
$a.EndInvoke($r1); $b.EndInvoke($r2); $c.EndInvoke($r3)

a done
b done
c done
0 голосов
/ 08 июля 2019

В этом примере выполняется параллельный пинг нескольких серверов, поэтому вы легко можете изменить его под свои требования:

Add-Type -AssemblyName System.Collections

$GH = [hashtable]::Synchronized(@{})

[System.Collections.Generic.List[PSObject]]$GH.results = @()
[System.Collections.Generic.List[string]]$GH.servers = @('server1','server2','server3');
[System.Collections.Generic.List[string]]$GH.functions = @('Check-Server');

[System.Collections.Generic.List[PSObject]]$jobs = @()


#-----------------------------------------------------------------
function Check-Server {
#-----------------------------------------------------------------

   # a function which runs parallel

   param(
        [string]$server
    )

    $result = Test-Connection $server -Count 1 -Quiet 
    $GH.results.Add( [PSObject]@{ 'Server' = $server; 'Result' = $result } )

}

#-----------------------------------------------------------------
function Create-InitialSessionState {
#-----------------------------------------------------------------

    param(
        [System.Collections.Generic.List[string]]$functionNameList
    )

    # Setting up an initial session state object
    $initialSessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()

    foreach( $functionName in $functionNameList ) {

        # Getting the function definition for the functions to add
        $functionDefinition = Get-Content function:\$functionName
        $functionEntry = New-Object System.Management.Automation.Runspaces.SessionStateFunctionEntry -ArgumentList $functionName, $functionDefinition

        # And add it to the iss object
        [void]$initialSessionState.Commands.Add($functionEntry)
    }

    return $initialSessionState
}

#-----------------------------------------------------------------
function Create-RunspacePool {
#-----------------------------------------------------------------

    param(
        [InitialSessionState]$initialSessionState
    )

    $runspacePool = [RunspaceFactory]::CreateRunspacePool(1, ([int]$env:NUMBER_OF_PROCESSORS + 1), $initialSessionState, $Host)
    $runspacePool.ApartmentState = 'MTA'
    $runspacePool.ThreadOptions  = "ReuseThread"
    [void]$runspacePool.Open()

    return $runspacePool
}


#-----------------------------------------------------------------
function Release-Runspaces {
#-----------------------------------------------------------------

    $runspaces = Get-Runspace | Where { $_.Id -gt 1 }

    foreach( $runspace in $runspaces ) {
        try{
            [void]$runspace.Close()
            [void]$runspace.Dispose()
            }
        catch {
        }
    }
}


$initialSessionState = Create-InitialSessionState -functionNameList $GH.functions
$runspacePool        = Create-RunspacePool -initialSessionState $initialSessionState


foreach ($server in $GH.servers)
{
    Write-Host $server

    $job = [System.Management.Automation.PowerShell]::Create($initialSessionState)
    $job.RunspacePool = $runspacePool

    $scriptBlock = { param ( [hashtable]$GH, [string]$server ); Check-Server -server $server }

    [void]$job.AddScript( $scriptBlock ).AddArgument( $GH ).AddArgument( $server )
    $jobs += New-Object PSObject -Property @{
                                    RunNum = $jobCounter++
                                    JobObj = $job
                                    Result = $job.BeginInvoke() }

    do {
        Sleep -Seconds 1 
    } while( $runspacePool.GetAvailableRunspaces() -lt 1 )

}

Do {
    Sleep -Seconds 1
} While( $jobs.Result.IsCompleted -contains $false)


$GH.results

Release-Runspaces | Out-Null

[void]$runspacePool.Close()
[void]$runspacePool.Dispose()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...