Multithreading & Syncronized Hashtable
Synchronized Hashtable
Multi-threading with Runspaces
http://cjoprey.blog.com/2009/08/17/asynchronicity-in-powershell/
http://newsqlblog.com/2012/05/22/concurrency-in-powershell-multi-threading-with-runspaces/
This example did not work for me, but I need to spend more time on it.
$newPowerShell = [PowerShell]::Create() $newPowerShell | gm $newPowerShell.InvocationStateInfo | gm $newPowerShell.InvocationStateInfo.State
Short version of code from Powershell Studio 2012
$form1_Load={ #TODO: Initialize Form Controls here $sharedData = [HashTable]::Synchronized(@{}) $sharedData.Foo = "bar" $sharedData.Status = "running" $Textbox1.Text = $sharedData.Foo $newRunspace = [RunSpaceFactory]::CreateRunspace() $newRunspace.ApartmentState = "STA" $newRunspace.ThreadOptions = "ReuseThread" $newRunspace.Open() $newRunspace.SessionStateProxy.setVariable("sharedData", $sharedData) $newPowerShell = [PowerShell]::Create() $newPowerShell.Runspace = $newRunspace } $buttonSingleClick_Click={ $this.Enabled = $False #TODO: Place custom script here $newPowerShell.AddScript({$sharedData.Foo = "fred"; sleep 5; $sharedData.Foo = "ddddd"; sleep 5; $sharedData.Status = "done"}).BeginInvoke() #Change while statement to check $newPowerShell.InvocationStateInfo.State while ($sharedData.Status -ne "done" ) { #Write-Host $sharedData.Foo $sharedData.Status $Textbox1.AppendText($sharedData.Foo + "`r`n") } #Process the pending messages before enabling the button [System.Windows.Forms.Application]::DoEvents() $this.Enabled = $True }
Long version of code from Powershell Studio 2012
Have not done this yet but evidently you can use the entire textbox inside the sycronized hashtable
$sharedData.Foo = [System.Windows.Forms.TextBox]$textbox1
Global Variables: $SharedVariable = [HashTable]::Synchronized(@{}) $NewPowerShell = $null Function AddTextboxToSharedVariable() { $SharedVariable.Add("OutputTB",[System.Windows.Forms.RichTextBox]$OutputRichTB) } Function NewPowershellSession() { $NewRunspace = [RunSpaceFactory]::CreateRunspace() $NewRunspace.ApartmentState = "STA" $NewRunspace.ThreadOptions = "ReuseThread" $NewRunspace.Open() $NewRunspace.SessionStateProxy.SetVariable("SharedVariable", $SharedVariable) $NewPowerShell = [PowerShell]::Create() $NewPowerShell.Runspace = $NewRunspace return $NewPowerShell } Function DisposeOldPowershellSession() { If ($NewPowerShell -ne $null) { $NewPowerShell.Runspace.Dispose() $NewPowerShell.Runspace = $null $NewPowerShell.Dispose() $NewPowerShell = $null } Function within main Thread invoking the Second Thread: Function Main() { AddTextboxToSharedVariable $ScriptBlock ={ Param ($User) Import-Module "C:\temp\MyFunctions.psm1" Get-USERGROUPSFROMAD $User $SharedVariable.OutputTB } DisposeOldPowershellSession $NewPowerShell = NewPowershellSession $NewPowerShell.AddScript($ScriptBlock) $NewPowerShell.AddParameter("User", $User) $Job = $NewPowerShell.BeginInvoke() }
blah blah
#------------------------------------------------------------------------ # Source File Information (DO NOT MODIFY) # Source ID: 9e3e6853-1b6a-4db1-af00-67e02dcdd5ea # Source File: C:\Users\currank\Documents\SAPIEN\PowerShell Studio 2012\Files\blah.pff #------------------------------------------------------------------------ #region File Recovery Data (DO NOT MODIFY) <#RecoveryData: IA8AAB+LCAAAAAAABADsvQdgHEmWJSYvbcp7f0r1StfgdKEIgGATJNiQQBDswYjN5pLsHWlHIymr KoHKZVZlXWYWQMztnbz33nvvvffee++997o7nU4n99//P1xmZAFs9s5K2smeIYCqyB8/fnwfPyIe v8qn1WVeXz/N2uzoN07S9PGXdXFRLLPyWVHmL7JFfjQps/l4dX7++G7vK34Bf/1kXjdFtTzaHe89 vut/ICAnP51P27S9XuWfffT6umnzxfi7xXJWXTXjZ1W9kH9HaeyrUaqgPtsf7+C/UXqyLtt1nX+2 zNdtnZWj9OV6UhbT3yu/flO9zZefTR48yO5P73+6+/Defr5z8PCjdEnIfvbROcHb/SidzotyVlO7 j06qZVtXZfMRo0mIvqyrVV631/rCSVnky/Z18YP8o6P9h7uj9P7u/uO7ptHASyDMR0fc141t3+Tv 2o+OMM5+09NL6lvbPa+ymcL8/fH747v8rWl6M33R0ZPq3c86iVvqZ1K920jlPhmeV9Ospf4/Onpw f5Tu3j/oUaP/zheEYVEWS6L1m3qd3+INmRiD4S1ekInf+5Qmfm/n4S1eeJNNzpaz/B291J/PuzJL t5+zJ+u2rZY/61M24W5eF8uLMieGn779unN37+DhbSdPpqLX8y3elDkBm+zdu0VzNyO3mXARR0Eo vS1GXzX5TxbNOitft9dl/iSbvj2pyqoeZktfsIXgfUr8/tp7IOY+B4V/HDdNvqDZzhvTVj+5PlLu +SJbZhf5gqCNj9dtteA5c1y0e1suurc7Ob93cP/TbHbv0/383v3Hd21P3Z4XzbSqy2LyDfDqhl5k fN9AHz9z8uj3VRn7fb8opnXVVOft+MXpm9/3WU1zdVXVb3/fS0C/t3Nv9+Hvq3SdleWNyH3jovv1 UA21y60Qh1fwc4YvOr8lmnV2RbLzdTDduXd+//zB+e7u7P5Odi/7mphK/7dD9vdelF8H0W+EpL/3 F89vh+TToiblUtXXr/P6spjmX4trvxnadjG53QBOqjr/Ojh/I2RG57dDUwdFRoJG9nNH5BCNCOr2 T2NiHr8kQ0cWpTYj+zxf5oSgZyalgY0TxIRFP9UPz6YaMARNw0/JjhXnedOe1DmbMNj13me29cm6 IVtnvvdgD33xssxauNlH2/AXzB/261fr5es3x0c7j+/qb8Yyh6N//DqfruuCXIS75hM/HuIPwqiJ Z7sfOQlOdTVbT9te487n3fZdwsc+fZo307pYhUS7G/30pFqssqXnxtztfXJSra4pQpwHhO5/drZs 85qiyA6C8Y+jIae8MPwVYbZwfpPi6n3y+G4QnhpOAy/TzPoR8f8TAAD//ze2pC0gDwAA#> #endregion #======================================================================== # Code Generated By: SAPIEN Technologies, Inc., PowerShell Studio 2012 v3.0.8 # Generated On: 24/10/2012 3:38 p.m. # Generated By: currank #======================================================================== #---------------------------------------------- #region Application Functions #---------------------------------------------- function OnApplicationLoad { #Note: This function is not called in Projects #Note: This function runs before the form is created #Note: To get the script directory in the Packager use: Split-Path $hostinvocation.MyCommand.path #Note: To get the console output in the Packager (Windows Mode) use: $ConsoleOutput (Type: System.Collections.ArrayList) #Important: Form controls cannot be accessed in this function #TODO: Add snapins and custom code to validate the application load return $true #return true for success or false for failure } function OnApplicationExit { #Note: This function is not called in Projects #Note: This function runs after the form is closed #TODO: Add custom code to clean up and unload snapins when the application exits $script:ExitCode = 0 #Set the exit code for the Packager } #endregion Application Functions #---------------------------------------------- # Generated Form Function #---------------------------------------------- function Call-blah_pff { #---------------------------------------------- #region Import the Assemblies #---------------------------------------------- [void][reflection.assembly]::Load("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") [void][reflection.assembly]::Load("System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") [void][reflection.assembly]::Load("System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") [void][reflection.assembly]::Load("System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") [void][reflection.assembly]::Load("System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") [void][reflection.assembly]::Load("System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") [void][reflection.assembly]::Load("System.DirectoryServices, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") [void][reflection.assembly]::Load("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") [void][reflection.assembly]::Load("System.ServiceProcess, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") #endregion Import Assemblies #---------------------------------------------- #region Generated Form Objects #---------------------------------------------- [System.Windows.Forms.Application]::EnableVisualStyles() $form1 = New-Object 'System.Windows.Forms.Form' $textbox1 = New-Object 'System.Windows.Forms.TextBox' $buttonSingleClick = New-Object 'System.Windows.Forms.Button' $InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState' #endregion Generated Form Objects #---------------------------------------------- # User Generated Script #---------------------------------------------- $form1_Load={ #TODO: Initialize Form Controls here $sharedData = [HashTable]::Synchronized(@{}) $sharedData.Foo = "bar" $sharedData.Status = "running" $Textbox1.Text = $sharedData.Foo $newRunspace = [RunSpaceFactory]::CreateRunspace() $newRunspace.ApartmentState = "STA" $newRunspace.ThreadOptions = "ReuseThread" $newRunspace.Open() $newRunspace.SessionStateProxy.setVariable("sharedData", $sharedData) $newPowerShell = [PowerShell]::Create() $newPowerShell.Runspace = $newRunspace } $buttonSingleClick_Click={ $this.Enabled = $False #TODO: Place custom script here $newPowerShell.AddScript({$sharedData.Foo = "fred"; sleep 5; $sharedData.Foo = "ddddd"; sleep 5; $sharedData.Status = "done"}).BeginInvoke() while ($sharedData.Status -ne "done" ) { #Write-Host $sharedData.Foo $sharedData.Status $Textbox1.AppendText($sharedData.Foo + "`r`n") } #Process the pending messages before enabling the button [System.Windows.Forms.Application]::DoEvents() $this.Enabled = $True } # --End User Generated Script-- #---------------------------------------------- #region Generated Events #---------------------------------------------- $Form_StateCorrection_Load= { #Correct the initial state of the form to prevent the .Net maximized form issue $form1.WindowState = $InitialFormWindowState } $Form_Cleanup_FormClosed= { #Remove all event handlers from the controls try { $buttonSingleClick.remove_Click($buttonSingleClick_Click) $form1.remove_Load($form1_Load) $form1.remove_Load($Form_StateCorrection_Load) $form1.remove_FormClosed($Form_Cleanup_FormClosed) } catch [Exception] { } } #endregion Generated Events #---------------------------------------------- #region Generated Form Code #---------------------------------------------- # # form1 # $form1.Controls.Add($textbox1) $form1.Controls.Add($buttonSingleClick) $form1.ClientSize = '491, 514' $form1.Name = "form1" $form1.Text = "Form" $form1.add_Load($form1_Load) # # textbox1 # $textbox1.Location = '75, 158' $textbox1.Multiline = $True $textbox1.Name = "textbox1" $textbox1.Size = '261, 209' $textbox1.TabIndex = 2 # # buttonSingleClick # $buttonSingleClick.Location = '389, 158' $buttonSingleClick.Name = "buttonSingleClick" $buttonSingleClick.Size = '75, 23' $buttonSingleClick.TabIndex = 1 $buttonSingleClick.Text = "Single Click" $buttonSingleClick.UseVisualStyleBackColor = $True $buttonSingleClick.add_Click($buttonSingleClick_Click) #endregion Generated Form Code #---------------------------------------------- #Save the initial state of the form $InitialFormWindowState = $form1.WindowState #Init the OnLoad event to correct the initial state of the form $form1.add_Load($Form_StateCorrection_Load) #Clean up the control events $form1.add_FormClosed($Form_Cleanup_FormClosed) #Show the Form return $form1.ShowDialog() } #End Function #Call OnApplicationLoad to initialize if((OnApplicationLoad) -eq $true) { #Call the form Call-blah_pff | Out-Null #Perform cleanup OnApplicationExit }