Informacje o zadaniach wątkuAbout Thread Jobs

Krótki opisShort description

Zawiera informacje dotyczące zadań opartych na wątkach programu PowerShell.Provides information about PowerShell thread-based jobs. Zadanie wątku jest typem zadania w tle, które uruchamia polecenie lub wyrażenie w osobnym wątku w ramach procesu bieżącej sesji.A thread job is a type of background job that runs a command or expression in a separate thread within the current session process.

Długi opisLong description

Program PowerShell jednocześnie uruchamia polecenia i skrypty za poorednictwem zadań.PowerShell concurrently runs commands and scripts through jobs. Program PowerShell udostępnia trzy typy zadań do obsługi współbieżności.There are three jobs types provided by PowerShell to support concurrency.

  • RemoteJob — Polecenia i skrypty są uruchamiane w sesji zdalnej.RemoteJob - Commands and scripts run in a remote session. Aby uzyskać więcej informacji, zobacz about_Remote_Jobs.For information, see about_Remote_Jobs.
  • BackgroundJob — Polecenia i skrypty są uruchamiane w osobnym procesie na komputerze lokalnym.BackgroundJob - Commands and scripts run in a separate process on the local machine. Aby uzyskać więcej informacji, zobacz opis polecenia about_Jobs.For more information, see about_Jobs.
  • PSTaskJob lub ThreadJob polecenia i skrypty są uruchamiane w osobnym wątku w ramach tego samego procesu na komputerze lokalnym.PSTaskJob or ThreadJob - Commands and scripts run in a separate thread within the same process on the local machine.

Zadania oparte na wątkach nie są tak niezawodne jak zadania zdalne i w tle, ponieważ są uruchamiane w tym samym procesie w różnych wątkach.Thread-based jobs are not as robust as remote and background jobs, because they run in the same process on different threads. Jeśli jedno zadanie ma krytyczny błąd powodujący awarię procesu, wszystkie pozostałe zadania w procesie zostaną zakończone.If one job has a critical error that crashes the process, then all other jobs in the process are terminated.

Zadania oparte na wątkach wymagają jednak mniejszego obciążenia.However, thread-based jobs require less overhead. Nie korzystają one z warstwy lub serializacji komunikacji zdalnej.They don't use the remoting layer or serialization. Obiekty wynikowe są zwracane jako odwołania do obiektów aktywnych w bieżącej sesji.The result objects are returned as references to live objects in the current session. Bez tego obciążenia zadania oparte na wątkach działają szybciej i używają mniej zasobów niż inne typy zadań.Without this overhead, thread-based jobs run faster and use fewer resources than the other job types.

Ważne

Sesja nadrzędna, która utworzyła zadanie, również monitoruje stan zadania i zbiera dane potoku.The parent session that created the job also monitors the job status and collects pipeline data. Proces podrzędny zadania jest zakończony przez proces nadrzędny, gdy zadanie osiągnie stan zakończenia.The job child process is terminated by the parent process once the job reaches a finished state. Jeśli sesja nadrzędna zostanie zakończona, wszystkie uruchomione zadania podrzędne zostaną zakończone wraz z ich procesami podrzędnymi.If the parent session is terminated, all running child jobs are terminated along with their child processes.

Istnieją dwa sposoby obejścia tej sytuacji:There are two ways work around this situation:

  1. Służy Invoke-Command do tworzenia zadań uruchamianych w odłączonych sesjach.Use Invoke-Command to create jobs that run in disconnected sessions. Aby uzyskać więcej informacji, zobacz about_Remote_Jobs.For more information, see about_Remote_Jobs.
  2. Służy Start-Process do tworzenia nowego procesu, a nie zadania.Use Start-Process to create a new process rather than a job. Aby uzyskać więcej informacji, zobacz Uruchamianie-proces.For more information, see Start-Process.

Jak uruchomić zadania oparte na wątkach i zarządzać nimiHow to start and manage thread-based jobs

Istnieją dwa sposoby uruchamiania zadań opartych na wątkach:There are two ways to start thread-based jobs:

  • Start-ThreadJob— z modułu ThreadJobStart-ThreadJob - from the ThreadJob module
  • ForEach-Object -Parallel -AsJob -Funkcja Parallel została dodana w programie PowerShell 7,0ForEach-Object -Parallel -AsJob - the parallel feature was added in PowerShell 7.0

Użyj tych samych poleceń cmdlet zadań opisanych w about_Jobs , aby zarządzać zadaniami opartymi na wątkach.Use the same Job cmdlets described in about_Jobs to manage thread-based jobs.

Korzystanie z akcji Start-ThreadJobUsing Start-ThreadJob

Moduł ThreadJob najpierw dostarczany z programem PowerShell 6.The ThreadJob module first shipped with PowerShell 6. Można go również zainstalować z Galeria programu PowerShell środowiska Windows PowerShell 5,1.It can also be installed from the PowerShell Gallery for Windows PowerShell 5.1.

Aby uruchomić zadanie wątku na komputerze lokalnym, użyj polecenia Start-ThreadJob cmdlet z poleceniem lub skryptem ujętym w nawiasy klamrowe ( { } ).To start a thread job on the local computer, use the Start-ThreadJob cmdlet with a command or script enclosed in curly braces ({ }).

Poniższy przykład uruchamia zadanie wątku, które uruchamia Get-Process polecenie na komputerze lokalnym.The following example starts a thread job that runs a Get-Process command on the local computer.

Start-ThreadJob -ScriptBlock { Get-Process }

Start-ThreadJobPolecenie zwraca ThreadJob obiekt, który reprezentuje uruchomione zadanie.The Start-ThreadJob command returns a ThreadJob object that represents the running job. Obiekt zadania zawiera przydatne informacje o zadaniu, w tym jego bieżący stan działania.The job object contains useful information about the job including its current running status. Zbiera wyniki zadania w miarę generowania wyników.It collects the results of the job as the results are being generated.

Korzystanie z akcji ForEach-Object -Parallel -AsJobUsing ForEach-Object -Parallel -AsJob

W programie PowerShell 7,0 dodano nowy parametr do ForEach-Object polecenia cmdlet.PowerShell 7.0 added a new parameter set to the ForEach-Object cmdlet. Nowe parametry umożliwiają uruchamianie bloków skryptów w wątkach równoległych jako zadań programu PowerShell.The new parameters allow you to run script blocks in parallel threads as PowerShell jobs.

Dane można potokować do ForEach-Object -Parallel .You can pipe data to ForEach-Object -Parallel. Dane są przesyłane do bloku skryptu, który jest uruchamiany równolegle.The data is passed to the script block that is run in parallel. -AsJobParametr tworzy obiekty zadań dla każdego z wątków równoległych.The -AsJob parameter creates jobs objects for each of the parallel threads.

Następujące polecenie uruchamia zadanie zawierające zadania podrzędne dla każdej wartości wejściowej potoku do polecenia.The following command starts a job that contains child jobs for each input value piped to the command. Każde zadanie podrzędne uruchamia Write-Output polecenie z potokową wartością wejściową jako argumentem.Each child job runs the Write-Output command with a piped input value as the argument.

1..5 | ForEach-Object -Parallel { Write-Output $_ } -AsJob

ForEach-Object -ParallelPolecenie zwraca PSTaskJob obiekt, który zawiera zadania podrzędne dla każdej wartości wejściowej potoku.The ForEach-Object -Parallel command returns a PSTaskJob object that contains child jobs for each piped input value. Obiekt zadania zawiera przydatne informacje o stanie uruchamiania zadań podrzędnych.The job object contains useful information about the child jobs running status. Zbiera wyniki zadań podrzędnych w miarę generowania wyników.It collects the results of the child jobs as the results are being generated.

Jak poczekać na ukończenie zadania i pobrać wyniki zadaniaHow to wait for a job to complete and retrieve job results

Możesz użyć poleceń cmdlet zadania programu PowerShell, takich jak Wait-Job i, Receive-Job aby poczekać na zakończenie zadania, a następnie zwrócić wszystkie wyniki wygenerowane przez zadanie.You can use PowerShell job cmdlets, such as Wait-Job and Receive-Job to wait for a job to complete and then return all results generated by the job.

Następujące polecenie uruchamia zadanie wątku, które uruchamia Get-Process polecenie, następnie czeka na ukończenie polecenia i zwraca wszystkie wyniki danych wygenerowane przez polecenie.The following command starts a thread job that runs a Get-Process command, then waits for the command to complete, and finally returns all data results generated by the command.

Start-ThreadJob -ScriptBlock { Get-Process } | Wait-Job | Receive-Job

Następujące polecenie uruchamia zadanie, które uruchamia Write-Output polecenie dla każdego potoku danych wejściowych, czeka na zakończenie wszystkich zadań podrzędnych i zwraca wszystkie wyniki danych wygenerowane przez zadania podrzędne.The following command starts a job that runs a Write-Output command for each piped input, then waits for all child jobs to complete, and finally returns all data results generated by the child jobs.

1..5 | ForEach-Object -Parallel { Write-Output $_ } -AsJob | Wait-Job | Receive-Job

Receive-JobPolecenie cmdlet zwraca wyniki zadań podrzędnych.The Receive-Job cmdlet returns the results of the child jobs.

1
3
2
4
5

Ponieważ każde zadanie podrzędne działa równolegle, kolejność wygenerowanych wyników nie jest gwarantowana.Because each child job runs parallel, the order of the generated results is not guaranteed.

Wydajność zadania wątkuThread job performance

Zadania wątków są szybsze i jaśniejsze niż inne typy zadań.Thread jobs are faster and lighter weight than other types of jobs. Jednak nadal mają narzuty, które mogą być duże, w porównaniu do pracy wykonywanej przez zadanie.But they still have overhead that can be large when compared to work the job is doing.

Program PowerShell uruchamia polecenia i skrypt w sesji.PowerShell runs commands and script in a session. W czasie sesji można uruchomić tylko jedno polecenie lub skrypt.Only one command or script can run at a time in a session. Tak więc w przypadku uruchamiania wielu zadań każde zadanie zostanie uruchomione w oddzielnej sesji.So when running multiple jobs, each job runs in a separate session. Każda sesja przyczynia się do narzutu.Each session contributes to the overhead.

Zadania wątków zapewniają najlepszą wydajność, gdy wykonywana praca jest większa niż obciążenie sesji używanej do uruchomienia zadania.Thread jobs provide the best performance when the work they perform is greater than the overhead of the session used to run the job. Istnieją dwa przypadki, w których spełnione są te kryteria.There are two cases for that meet this criteria.

  • Praca polega na intensywnym obliczaniu działania skryptu w wielu zadaniach wątków. można korzystać z wielu rdzeni procesora i wykonywać szybsze działanie.Work is compute intensive - Running a script on multiple thread jobs can take advantage of multiple processor cores and complete faster.

  • Pracy składa się z znaczącego oczekiwania — skryptu, który poświęca czas na oczekiwanie na we/wy lub zdalne wyniki wywołań.Work consists of significant waiting - A script that spends time waiting for I/O or remote call results. Uruchamianie równoległe zwykle kończy się szybciej niż w przypadku sekwencyjnego uruchamiania.Running in parallel usually completes quicker than if run sequentially.

(Measure-Command {
    1..1000 | ForEach { Start-ThreadJob { Write-Output "Hello $using:_" } } | Receive-Job -Wait
}).TotalMilliseconds
36860.8226

(Measure-Command {
    1..1000 | ForEach-Object { "Hello: $_" }
}).TotalMilliseconds
7.1975

W pierwszym powyższym przykładzie przedstawiono pętlę Foreach, która tworzy zadania wątku 1000 w celu wykonania prostego zapisu w postaci ciągu.The first example above shows a foreach loop that creates 1000 thread jobs to do a simple string write. Ze względu na obciążenie zadania trwa ponad 36 sekund.Due to job overhead, it takes over 36 seconds to complete.

Drugi przykład uruchamia ForEach polecenie cmdlet, aby wykonać te same operacje 1000.The second example runs the ForEach cmdlet to do the same 1000 operations. Ten czas ForEach-Object działa sekwencyjnie, w pojedynczym wątku, bez konieczności wykonywania zadań.This time, ForEach-Object runs sequentially, on a single thread, without any job overhead. Jest ona uzupełniana o co najprawdopodobniej 7 milisekund.It completes in a mere 7 milliseconds.

W poniższym przykładzie do 10 oddzielnych dzienników systemu zbierane są wpisy do 5000.In the following example, up to 5000 entries are collected for 10 separate system logs. Ponieważ skrypt wymaga odczytania wielu dzienników, warto wykonać operacje równolegle.Since the script involves reading a number of logs, it makes sense to do the operations in parallel.

$logNames.count
10

Measure-Command {
    $logs = $logNames | ForEach-Object {
        Get-WinEvent -LogName $_ -MaxEvents 5000 2>$null
    }
}

TotalMilliseconds : 252398.4321 (4 minutes 12 seconds)
$logs.Count
50000

Skrypt kończy pracę w czasie, gdy zadania są uruchamiane równolegle.The script completes in half the time when the jobs are run in parallel.

Measure-Command {
    $logs = $logNames | ForEach {
        Start-ThreadJob {
            Get-WinEvent -LogName $using:_ -MaxEvents 5000 2>$null
        } -ThrottleLimit 10
    } | Wait-Job | Receive-Job
}

TotalMilliseconds : 115994.3 (1 minute 56 seconds)
$logs.Count
50000

Zadania wątku i zmienneThread jobs and variables

Istnieje wiele sposobów przekazywania wartości do zadań opartych na wątkach.There are multiple ways to pass values into the thread-based jobs.

Start-ThreadJob można akceptować zmienne, które są potokowe w potoku do polecenia cmdlet, przekazane do bloku skryptu za pośrednictwem $using słowa kluczowego lub przekazane za pośrednictwem parametru listaargumentów .Start-ThreadJob can accept variables that are piped to the cmdlet, passed in to the script block via the $using keyword, or passed in via the ArgumentList parameter.

$msg = "Hello"

$msg | Start-ThreadJob { $input | Write-Output } | Wait-Job | Receive-Job

Start-ThreadJob { Write-Output $using:msg } | Wait-Job | Receive-Job

Start-ThreadJob { param ([string] $message) Write-Output $message } -ArgumentList @($msg) |
  Wait-Job | Receive-Job

ForEach-Object -Parallel akceptuje potoki w zmiennych, a zmienne przekazane bezpośrednio do bloku skryptu za pomocą $using słowa kluczowego.ForEach-Object -Parallel accepts piped in variables, and variables passed directly to the script block via the $using keyword.

$msg = "Hello"

$msg | ForEach-Object -Parallel { Write-Output $_ } -AsJob | Wait-Job | Receive-Job

1..1 | ForEach-Object -Parallel { Write-Output $using:msg } -AsJob | Wait-Job | Receive-Job

Ponieważ zadania wątków są uruchamiane w tym samym procesie, wszystkie typy odwołań do zmiennych, które są przesyłane do zadania, należy uważnie traktować.Since thread jobs run in the same process, any variable reference type passed into the job has to be treated carefully. Jeśli nie jest to obiekt bezpiecznego wątku, wówczas nigdy nie powinien być przypisany do, a metody i właściwości nie powinny być wywoływane na nim.If it is not a thread safe object, then it should never be assigned to, and method and properties should never be invoked on it.

Poniższy przykład przekazuje bezpieczny wątkowo ConcurrentDictionary obiekt .NET do wszystkich zadań podrzędnych, aby zbierać obiekty z unikatowymi nazwami procesów.The following example passes a thread-safe .NET ConcurrentDictionary object to all child jobs to collect uniquely named process objects. Ponieważ jest to obiekt bezpieczny wątkowo, może być bezpiecznie używany podczas wykonywania zadań współbieżnie w procesie.Since it is a thread safe object, it can be safely used while the jobs run concurrently in the process.

$threadSafeDictionary = [System.Collections.Concurrent.ConcurrentDictionary[string,object]]::new()
$jobs = Get-Process | ForEach {
    Start-ThreadJob {
        $proc = $using:_
        $dict = $using:threadSafeDictionary
        $dict.TryAdd($proc.ProcessName, $proc)
    }
}
$jobs | Wait-Job | Receive-Job

$threadSafeDictionary.Count
96

$threadSafeDictionary["pwsh"]

NPM(K)  PM(M)   WS(M) CPU(s)    Id SI ProcessName
------  -----   ----- ------    -- -- -----------
  112  108.25  124.43  69.75 16272  1 pwsh

Zobacz takżeSee also