Closed dave1000 closed 9 years ago
When you say 'passing as an argument', are using the -Argument parameter in Start-RSJob?
Looks like the ArrayList is not being passed into the function via -ArgumentList. Will have to determine what is going on and how to fix it. For the time being, I would recommend using the $Using: variable scope to bring in the ArrayList as it does work properly.
$SyncList = [System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList))
1|Start-RSJob {($Using:SyncList).Add(1)} -Verbose|Wait-RSJob|Remove-RSJob
$SyncList
Try the latest version (1.5.2.0) as it should fix the issue.
Hi Boe
I have tried the latest version which is 1.5.3.0 in the readme. Are you referring to being able to use the $Using in this latest version or that it should resolve the original issue. I have tested it and the arraylist still does not get modified when passed as an argument. I didn't realize you could modify an object using $Using as well as passing it to the runspace so I will give this a try.
Thanks
Yea, I had to fix a bug in the Pester test that got introduced by my troubleshooting of this issue. Can you comment with the code that you are using so I can see if I can duplicate the issue? In my testing with the synchronized arraylist, I was able to pass it in and update it so I want to make sure I am testing it in the way that you are using it.
The $Using: has been around for a little while and it is definitely the preferred approach to this but I would like to see if I can fix the other issue as well.
Yea, I had to fix a bug in the Pester test that got introduced by my troubleshooting of this issue. Can you comment with the code that you are using so I can see if I can duplicate the issue? In my testing with the synchronized arraylist, I was able to pass it in and update it so I want to make sure I am testing it in the way that you are using it.
The $Using: has been around for a little while and it is definitely the preferred approach to this but I would like to see if I can fix the other issue as well.
$arrayList = [System.Collections.ArrayList]::Synchronized((New-Object system.Collections.ArrayList));
1 | Start-RSJob -ScriptBlock { Param ( $arrayList )
$arrayList.Add("Test1");
[System.Threading.Monitor]::Exit($arrayList.SyncRoot);
} -ArgumentList $arrayList;
Import-Module PoshRSJob;
$arrayList = [System.Collections.ArrayList]::Synchronized((New-Object system.Collections.ArrayList));
Start-RSJob -ScriptBlock { Param ( $arrayList )
$arrayList.Add("Test1");
[System.Threading.Monitor]::Exit($arrayList.SyncRoot);
} -ArgumentList $arrayList;
$arrayList = [System.Collections.ArrayList]::Synchronized((New-Object system.Collections.ArrayList));
1..10 | Start-RSJob -ScriptBlock { Param ( $arrayList )
$arrayList.Add("Test1");
[System.Threading.Monitor]::Exit($arrayList.SyncRoot);
} -ArgumentList $arrayList;
Exception calling "Enter" with "1" argument(s): "Value cannot be null." At line:6 char:1
- CategoryInfo : NotSpecified: (:) [], MethodInvocationException
- FullyQualifiedErrorId : ArgumentNullException
You cannot call a method on a null-valued expression. At line:7 char:1
- CategoryInfo : InvalidOperation: (:) [], RuntimeException
- FullyQualifiedErrorId : InvokeMethodOnNull
Exception calling "Exit" with "1" argument(s): "Value cannot be null." At line:8 char:1
- CategoryInfo : NotSpecified: (:) [], MethodInvocationException
## \+ FullyQualifiedErrorId : ArgumentNullException
In 3. any one of the jobs will succeed but the others will produce the same above error.
Thanks. I will look at all of these and test to come up with a possible solution.
I think I have number 2 solved but number 3 is an odd issue. It appears to pass the collection fine on the initial run but the subsequent RSJobs are only recognizing the value as a string which is why you are getting the errors. I'm digging more into this and will see what I can find.
I've finished a fix for this that I tested against your examples, all of which succeeded. I'll try to get this updated later tonight.
Check out the latest update (V1.5.5.0) and let me know if you are seeing the issue happening.
Hi Boe
This is all working fine now, thanks for the quick fix.
Dave
Passing synchronized hashtable as argument does not work again.
This does not work:
$hash = [hashtable]::Synchronized(@{Number=0})
$sb = {
param($syncHash)
[System.Threading.Monitor]::Enter($syncHash.SyncRoot)
$syncHash.Number += 10
[System.Threading.Monitor]::Exit($syncHash.SyncRoot)
}
1..10 | Start-RSJob -Name {$_} -ScriptBlock $sb -ArgumentList $hash | Wait-RSJob | Receive-RSJob
Error:
Exception calling "Enter" with "1" argument(s): "Value cannot be null."
The property 'Number' cannot be found on this object. Verify that the property exists and can be set.
Exception calling "Exit" with "1" argument(s): "Value cannot be null."
This works perfectly:
$hash = [hashtable]::Synchronized(@{Number=0})
$sb = {
($using:hash).Number += 10
}
1..10 | Start-RSJob -Name {$_} -ScriptBlock $sb | Wait-RSJob | Receive-RSJob
Components: Powershell 5.0 PoshRSJob 1.7.3.7
Passing synchronized arraylist as an argument, using [System.Threading.Monitor]::Enter(***.SyncRoot) to lock the object and adding a new member never gets saved to the array, doesn't throw error. You can only modify an object such as PSObject that has already been added to the array. Works fine with a synchronized hash table. If you manually create a runspace not using PoshRSJob the arraylist works fine.
Thanks