mirror of
https://github.com/freedbygrace/Invoke-PSThread.git
synced 2026-07-26 11:28:14 +00:00
36c14aa790dd989c34f7188c9c747b527f8e8293
Invoke-PSThread
.SYNOPSIS
Enables the ability to leverage multithreading within powershell whilst reducing the complexity to get started.
.DESCRIPTION
This function aims to remove the enormous complexity out of multithreading within powershell. See the fully working examples below.
.PARAMETER Runspace
Your parameter description
.PARAMETER RunspacePool
Your parameter description
.PARAMETER Await
Your parameter description
.PARAMETER RunspaceDefinition
Your parameter description
.PARAMETER RunspaceParameters
Your parameter description
.PARAMETER InputObjectList
Your parameter description
.PARAMETER SynchronizedHashtable
Your parameter description
.PARAMETER AssemblyList
Your parameter description
.PARAMETER FunctionList
Your parameter description
.PARAMETER ModuleList
Your parameter description
.PARAMETER VariableList
Your parameter description
.PARAMETER ThreadList
Your parameter description
.PARAMETER LoopTimeout
Your parameter description
.PARAMETER LoopDuration
Your parameter description
.PARAMETER WaitForAvailableRunspace
Your parameter description
.PARAMETER ContinueOnError
Your parameter description
.EXAMPLE
Create a runspace
[ScriptBlock]$RunspaceDefinition = {
Param
(
$SynchronizedHashtable,
$Title,
$Message
)
$Null = Add-Type -AssemblyName 'System.Windows.Forms'
$Null = Add-Type -AssemblyName 'System.Drawing'
$Form = New-Object -TypeName 'System.Windows.Forms.Form'
$Form.Size = New-Object -TypeName 'System.Drawing.Size' -ArgumentList @(300,150)
$TextBox = New-Object -TypeName 'System.Windows.Forms.RichTextBox'
$TextBox.Location = New-Object -TypeName 'System.Drawing.Point' -ArgumentList @(110,50)
$TextBox.BorderStyle = 0
$TextBox.BackColor = $Form.BackColor
$TextBox.Text = $Message
$Null = $Form.Controls.Add($TextBox)
$Null = $Form.ShowDialog()
}
$SynchronizedHashtable = [System.Collections.Hashtable]::Synchronized(@{})
$SynchronizedHashtable.ThreadIDList = New-Object -TypeName 'System.Collections.Generic.List[System.String]'
$InvokePSThreadParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
$InvokePSThreadParameters.Runspace = $True
$InvokePSThreadParameters.RunspaceDefinition = $RunspaceDefinition
$InvokePSThreadParameters.RunspaceParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
$InvokePSThreadParameters.RunspaceParameters.Title = "This is my UI title"
$InvokePSThreadParameters.RunspaceParameters.Message = "This is my UI message.`r`nThis is the second line of my UI message.`r`nThis is the third line of my UI message."
$InvokePSThreadParameters.SynchronizedHashtable = Get-Variable -Name 'SynchronizedHashtable' -ErrorAction SilentlyContinue
$InvokePSThreadParameters.FunctionList = Get-ChildItem -Path 'Function:' | Where-Object {($_.Name -iin @('Test'))}
$InvokePSThreadParameters.ModuleList = Get-Module | Where-Object {($_.Name -iin @('Test'))}
$InvokePSThreadParameters.VariableList = Get-Variable | Where-Object {($_.Name -iin @('Test'))}
$InvokePSThreadParameters.ContinueOnError = $False
$InvokePSThreadParameters.Verbose = $True
$InvokePSThreadResult = Invoke-PSThread @InvokePSThreadParameters
Write-Output -InputObject ($InvokePSThreadResult)
.EXAMPLE
Create a runspace pool, submit all jobs to the pool, and the pool will manage their execution.
[ScriptBlock]$RunspaceDefinition = {
Param
(
$InputObjectListItem,
$SynchronizedHashtable,
$AdditionalParameter1,
$AdditionalParameter2
)
#Set thread priority
[System.Threading.Thread]::CurrentThread.Priority = [System.Threading.ThreadPriority]::Lowest
$ThreadInfo = [System.Threading.Thread]::CurrentThread
$ThreadID = [System.AppDomain]::GetCurrentThreadId()
$SynchronizedHashtable.ThreadIDList.Add($ThreadID)
Write-Verbose -Message "Attempting to begin thread ID `"$($ThreadID)`". Please Wait..." -Verbose
$SynchronizedHashtable.Add("Thread$($ThreadID)", (Get-Date))
Write-Output -InputObject ($InputObjectListItem)
Write-Output -InputObject ($AdditionalParameter1)
Write-Output -InputObject ($AdditionalParameter2)
$Null = Start-Sleep -Seconds (Get-Random -Minimum 10 -Maximum 25)
}
$SynchronizedHashtable = [System.Collections.Hashtable]::Synchronized(@{})
$SynchronizedHashtable.ThreadIDList = New-Object -TypeName 'System.Collections.Generic.List[System.String]'
$InvokePSThreadParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
$InvokePSThreadParameters.RunspacePool = $True
$InvokePSThreadParameters.InputObjectList = 1..15
$InvokePSThreadParameters.RunspaceDefinition = $RunspaceDefinition
$InvokePSThreadParameters.RunspaceParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
$InvokePSThreadParameters.RunspaceParameters.AdditionalParameter1 = Get-Random -Minimum 0 -Maximum 10000
$InvokePSThreadParameters.RunspaceParameters.AdditionalParameter2 = Get-Random -Minimum 0 -Maximum 10000
$InvokePSThreadParameters.SynchronizedHashtable = Get-Variable -Name 'SynchronizedHashtable' -ErrorAction SilentlyContinue
$InvokePSThreadParameters.FunctionList = Get-ChildItem -Path 'Function:' | Where-Object {($_.Name -iin @('Test'))}
$InvokePSThreadParameters.ModuleList = Get-Module | Where-Object {($_.Name -iin @('Test'))}
$InvokePSThreadParameters.VariableList = Get-Variable | Where-Object {($_.Name -iin @('Test'))}
$InvokePSThreadParameters.ContinueOnError = $False
$InvokePSThreadParameters.Verbose = $True
$InvokePSThreadResult = Invoke-PSThread @InvokePSThreadParameters
Write-Output -InputObject ($InvokePSThreadResult)
.EXAMPLE
Create a runspace pool, submit all jobs to the pool, and the pool will manage their execution. The function will be executed a second time to wait until all jobs have been completed, return their output, and cleanup.
[ScriptBlock]$RunspaceDefinition = {
Param
(
$InputObjectListItem,
$SynchronizedHashtable,
$AdditionalParameter1,
$AdditionalParameter2
)
#Set thread priority
[System.Threading.Thread]::CurrentThread.Priority = [System.Threading.ThreadPriority]::Lowest
$ThreadInfo = [System.Threading.Thread]::CurrentThread
$ThreadID = [System.AppDomain]::GetCurrentThreadId()
$SynchronizedHashtable.ThreadIDList.Add($ThreadID)
Write-Verbose -Message "Attempting to begin thread ID `"$($ThreadID)`". Please Wait..." -Verbose
$SynchronizedHashtable.Add("Thread$($ThreadID)", (Get-Date))
Write-Output -InputObject ($InputObjectListItem)
Write-Output -InputObject ($AdditionalParameter1)
Write-Output -InputObject ($AdditionalParameter2)
$Null = Start-Sleep -Seconds (Get-Random -Minimum 10 -Maximum 25)
}
$SynchronizedHashtable = [System.Collections.Hashtable]::Synchronized(@{})
$SynchronizedHashtable.ThreadIDList = New-Object -TypeName 'System.Collections.Generic.List[System.String]'
$InvokePSThreadParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
$InvokePSThreadParameters.RunspacePool = $True
$InvokePSThreadParameters.InputObjectList = Get-Process | Get-Random -Count 15
$InvokePSThreadParameters.RunspaceDefinition = $RunspaceDefinition
$InvokePSThreadParameters.RunspaceParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
$InvokePSThreadParameters.RunspaceParameters.AdditionalParameter1 = Get-Random -Minimum 0 -Maximum 10000
$InvokePSThreadParameters.RunspaceParameters.AdditionalParameter2 = Get-Random -Minimum 0 -Maximum 10000
$InvokePSThreadParameters.SynchronizedHashtable = Get-Variable -Name 'SynchronizedHashtable' -ErrorAction SilentlyContinue
$InvokePSThreadParameters.FunctionList = Get-ChildItem -Path 'Function:' | Where-Object {($_.Name -iin @('Test'))}
$InvokePSThreadParameters.ModuleList = Get-Module | Where-Object {($_.Name -iin @('Test'))}
$InvokePSThreadParameters.VariableList = Get-Variable | Where-Object {($_.Name -iin @('Test'))}
$InvokePSThreadParameters.ContinueOnError = $False
$InvokePSThreadParameters.Verbose = $True
$InvokePSThreadResult = Invoke-PSThread @InvokePSThreadParameters
#Do some additional code here
$InvokePSThreadParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
$InvokePSThreadParameters.Await = $True
$InvokePSThreadParameters.ThreadList = $InvokePSThreadResult
$InvokePSThreadParameters.LoopTimeout = [System.TimeSpan]::FromHours(1)
$InvokePSThreadParameters.LoopDuration = [System.TimeSpan]::FromMilliseconds(15000)
$InvokePSThreadParameters.ContinueOnError = $False
$InvokePSThreadParameters.Verbose = $True
$ThreadAwaitResult = Invoke-PSThread @InvokePSThreadParameters
Write-Output -InputObject ($ThreadAwaitResult)
.NOTES
Any useful tidbits
.LINK
https://davewyatt.wordpress.com/2014/04/29/more-potential-use-cases-for-thread-safe-variable-access-in-powershell-events/
.LINK
https://davewyatt.wordpress.com/2014/04/29/more-potential-use-cases-for-thread-safe-variable-access-in-powershell-events/
.LINK
https://www.codeproject.com/Tips/895840/Multi-Threaded-PowerShell-Cookbook
.LINK
https://www.linkedin.com/pulse/multithreading-powershell-scripts-alexey/
.LINK
https://xkln.net/blog/multithreading-in-powershell--running-a-specific-number-of-threads/
.LINK
https://markw.dev/#:~:text=There%20are%20two%20ways%20we,other%20is%20by%20using%20splatting.&text=The%20important%20part%20here%20is,plural)%20instead%20of%20AddParameter()%20.
Languages
PowerShell
100%