Reputation: 87
I have a WPF script running into problems recently.
The script does subnet scanning using PSParallel module. When the subnet CIDR is less than 21, it starts having the problem.
The problem is: I have a concurrent queue as a member of a synchronized hash table. The queue is used for producer/consumer model. The scanning threads keep enqueue the data and the GUI thread keep dequeue data and write it to a richtextbox. The dequeue process is handled by a dispatch timer event handler, which is executed every 20 ms. When the CIDR >=21, there is no problem. But when CIDR <21, sometimes it will throw an error message:
Collection was modified; enumeration operation may not execute.
At E:\PSScanner\PSScanner.ps1:446 char:8
+ if($syncHash.Q.Count -ne 0){
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], InvalidOperationException
+ FullyQualifiedErrorId : System.InvalidOperationException
I think the synchronized hash table is thread safe and the concurrent queue is thread safe as well. Not sure why is this happening.
The source code is here: https://github.com/MeCRO-DEV/PSScanner
Upvotes: 3
Views: 1284
Reputation: 87
I fixed the problem eventually.
I was calling a scriptblock stored in a synchronized hash table: $syncHash.Output, which send the output string to a concurrent queue. That scriptblock causes the output messed up and the worker threads terminated unexpectedly. After enqueue the data directly, instead of calling the scriptblock, problem solved.
Also, I have an IP counter $syncHash.Count. I thought it should be thread-safe as it is stored in the synchronized hash table, but actually it is not. I was getting inaccurate counts every time. After setting up a mutex to protect the counter variable, it works perfectly. The only reason I was thinking is the counter is updated in worker threads which are PSParallel instances(Invoke-Parallel cmdlet). Not sure how it handles the hash table.
Thank you all for your help.
Upvotes: 1