Runspaces with Winform, are they disposed ?

Ask questions about creating Graphical User Interfaces (GUI) in PowerShell and using WinForms controls.
Forum rules
Do not post any licensing information in this forum.

Any code longer than three lines should be added as code using the 'Select Code' dropdown menu or attached as a file.
Locked
User avatar
zztemp
Posts: 24
Joined: Mon Apr 03, 2017 6:58 am

Runspaces with Winform, are they disposed ?

Post by zztemp » Thu Jul 12, 2018 6:38 am

So i posted a question earlier last week : viewtopic.php?f=21&t=12723&p=68539#p68539
I got that figured out but it got me interested in runspaces all together.
Therefore i started reading a lot and made a list of different possibilities and saved them to my github as a learning experience : https://github.com/CookieCrumbles/Runsp ... amples.ps1

Anyway, i have been testing stuff and i created a simple form that has 3 computergroups that exist in AD.
It should retrieve its members. then get extra info on those machines and report back. I want this done in a runspace so that my GUI remains responsive and so that the user might trigger a secondary request.

In attachment the code that i made. This works BUT i am thinking that my runspaces aren't getting disposed off.
Debugging this is really hard since i don't have enough experience just yet.

Could someone have a look at the code i wrote and maybe tell me if there is a better way, even if it's either a slight adjustment of a complete re-write?

Cheers.
Attachments
Example.psf
(26.79 KiB) Downloaded 8 times

User avatar
jvierra
Posts: 12646
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: Runspaces with Winform, are they disposed ?

Post by jvierra » Thu Jul 12, 2018 6:40 am

When finished with the runspace just "Dispose" it. It the variables are removed or they go out-of-scope the system will automatically dispose the runspace.

User avatar
jvierra
Posts: 12646
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: Runspaces with Winform, are they disposed ?

Post by jvierra » Thu Jul 12, 2018 6:54 am

Since you are not executing the runspace "async" then there is no gain by using a runspace. What you are trying to do would be better served and managed using jobs. Jobs always run async and you can easily create many and mange them easily with the JobTracker control set.

Rule #1 of programming. Don't use a more complex method than required by the task.

In your example you are disposing of the PowerSHell instance which will not remove the runspace.

To remove the runspace don't create a separate variable. Just assign it to the PowerShell instance.

Code: Select all

	$newPowerShell = [PowerShell]::Create() # Create powershell instance
	$newPowerShell.Runspace =[RunSpaceFactory]::CreateRunspace()
        $newPowerShell.Runspace.ThreadOptions = 'ReuseThread'
	$newPowerShell.Runspace.ApartmentState = 'STA'
	$newPowerShell.Runspace.Open()
	$newPowerShell.Runspace.SessionStateProxy.setVariable('sharedData', $sharedData)
The above eliminates the extra variables. Disposing of "$newPowerShell" will also dispose of the runspace.

You can create a global array and add new PowerShell objects to it. Use "InvokeAsync" to allow the code to continue.

User avatar
zztemp
Posts: 24
Joined: Mon Apr 03, 2017 6:58 am

Re: Runspaces with Winform, are they disposed ?

Post by zztemp » Thu Jul 12, 2018 7:03 am

Hi,

Thanks for helping again.
Well the main reason for me using runspaces, is because i want to learn how it works.
The task at hand might not be best suited for it, but its a simple job from which i know what to expect as output.
I gotta start small.

You say i am not running my runspace "async". But it runs " a long side" my other thread so doesn't that make it async ?
I know there is the .OpenAsync method but haven't used that just yet.
also, i have a $handle = $newPowerShell.AddScript({..})..BeginInvoke() i thought to have read that this made is into an async object?
Sorry if i'm making stupid mistakes or remarks, this is quite the subject to get into, but fun!

At this moment, with the code i have, am i correct to say that if ($handle.IsCompleted -eq $true) doesn't do much?

User avatar
jvierra
Posts: 12646
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: Runspaces with Winform, are they disposed ?

Post by jvierra » Thu Jul 12, 2018 7:29 am

I forgot to note that you should use a runspace pool. Assign the pool to the PS instance and set the pool for the min and max number of runspaces. The pool will recycle the runspaces as needed, Tis will allow you to do most things with a pool of 5.

Consider the following:

Code: Select all

# configure pool
$iss = [initialsessionstate]::Create()
$iss.ApartmentState = 'STA'
$iss.ThreadOptions = 'ReuseThread'
$iss.LanguageMode = 'FullLanguage'
$customRSPool = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspacePool(1,4,$iss,$host)
$customRSPool.Open()

# create a PS and assign it to the pool
$ps = [powershell]::Create()
$ps.RunspacePool = $customRSPool
To remove all runspaces just do the following:

$customRSPool.Close()
$customRSPool.Dispose()


Runspaces in the pool can be recycled as needed.

User avatar
zztemp
Posts: 24
Joined: Mon Apr 03, 2017 6:58 am

Re: Runspaces with Winform, are they disposed ?

Post by zztemp » Thu Jul 12, 2018 7:34 am

I tried with the pool but i couldn't find out how i should pass the sharedData variable. I tried to pass it a long to the runspace but it kept notifying me that it wasn't possible. So i figured i just simplify and just try with one powershell instance and runspace. But yes a pool would be better.
If i understood correctly, if you create a pool then you cant have *too many* instances because it are *managed* instances.
In the current state, if i were to click my button a thousand times, it would create\cause problems. With the pool it would take care of business for me.

User avatar
jvierra
Posts: 12646
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: Runspaces with Winform, are they disposed ?

Post by jvierra » Thu Jul 12, 2018 8:45 am

zztemp wrote:
Thu Jul 12, 2018 7:34 am
I tried with the pool but i couldn't find out how i should pass the sharedData variable. I tried to pass it a long to the runspace but it kept notifying me that it wasn't possible. So i figured i just simplify and just try with one powershell instance and runspace. But yes a pool would be better.
If i understood correctly, if you create a pool then you cant have *too many* instances because it are *managed* instances.
In the current state, if i were to click my button a thousand times, it would create\cause problems. With the pool it would take care of business for me.
Close to correct. The "Invoke" will wait until the script completes or fails. BeginInvoke() will not wait. It returns an async object that can be inspected for completion and it will have any returned data or errors.

See:
https://docs.microsoft.com/en-us/dotnet ... eginInvoke

User avatar
jvierra
Posts: 12646
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: Runspaces with Winform, are they disposed ?

Post by jvierra » Thu Jul 12, 2018 8:57 am

Here is a pretty good explanation of how to use runspaces without blocking:

https://learn-powershell.net/2016/02/14 ... -runspace/

User avatar
zztemp
Posts: 24
Joined: Mon Apr 03, 2017 6:58 am

Re: Runspaces with Winform, are they disposed ?

Post by zztemp » Tue Jul 17, 2018 3:39 am

So i wanted to thank you for pointing me into the direction i needed.
I've copy\pasted the general outline of how i'm doing it now. This way works perfectly.
On one clickevent i know have 2 runspaces started, one for doing the actual work and a second one to go through a imagelist and showing an animated gif as the background image for my button.

It comes down to the following.

Code: Select all

$sharedData = [HashTable]::Synchronized(@{ }) #Create new sync hashtable to transfer\share data between runspaces.
	$sharedData.data = @()
	$sharedData.Groups = $target_groups # name of selected item
	
	# configure pool
	$iss = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
	$iss.ApartmentState = 'STA'
	$iss.ThreadOptions = 'ReuseThread'
	$iss.LanguageMode = 'FullLanguage'
		$SharedData = New-object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'sharedData', $sharedData, $Null
	$ISSbuttonSearch = New-object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'ISSbuttonSearch', $btnSearch, $Null
	$ISSimagelist1 = New-object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'ISSimagelist1', $imagelist1, $Null
	
	#Add the variable to the sessionstate
	$iss.Variables.Add($SharedData)
	$iss.Variables.Add($ISSbuttonSearch)
	$iss.Variables.Add($ISSimagelist1)
	
	# Create custom pool
	$customRSPool = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspacePool(1, 4, $iss, $host)
	$customRSPool.Open()
	
	$global:newPowerShell2 = [powershell]::Create()
	$newPowerShell2.RunspacePool = $customRSPool
	$global:handleImage = $newPowerShell2.AddScript({
	\\ do stuff here
	}).BeginInvoke()
	
	#region Cleanup runspaces
	if ($handleImage.IsCompleted)
	{
		$customRSPool.Close()
		$customRSPool.Dispose()
		[System.GC]::Collect()
	}
I post this so that it might help others even tho it might not be perfect. I still am new to this and have a lot to learn.

I found that debugging runspaces is really hard and the main debugging happend in my head with logical thinking.
One way i found to debug it was to use the following code in ISE

Code: Select all

Get-PSHostProcessInfo | Where-Object { $_.MainWindowTitle -eq 'MainWindow' } | Enter-PSHostProcess
Get-Runspace | Where-Object { $_.Debugger.InBreakpoint -eq $true } | Debug-Runspace
In your actual code you add : wait-debugger
You can then walk through the code per line in the ISE.
For some reason this didn't always work. It sometimes showed me the full code of my application, but sometimes it didn't.
It seemed to depend on where you add your wait-debugger

Anyway, i'll be working with runspaces a lot more. The possibilities with it are awesome!
Jvierra, thanks again.

User avatar
jvierra
Posts: 12646
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: Runspaces with Winform, are they disposed ?

Post by jvierra » Tue Jul 17, 2018 3:46 am

Great. Have fun.

Locked