首页 > 解决方案 > Powershell 同步哈希表线程安全

问题描述

我最近有一个 WPF 脚本遇到问题。

该脚本使用 PSParallel 模块进行子网扫描。当子网 CIDR 小于 21 时,它开始出现问题。

问题是:我有一个并发队列作为同步哈希表的成员。队列用于生产者/消费者模型。扫描线程保持数据入队,GUI线程保持数据出队并将其写入富文本框。出队过程由调度计时器事件处理程序处理,该事件处理程序每​​ 20 毫秒执行一次。当 CIDR >=21 时,没有问题。但是当 CIDR <21 时,有时会抛出错误信息:

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

我认为同步哈希表是线程安全的,并发队列也是线程安全的。不知道为什么会这样。

源代码在这里: https ://github.com/MeCRO-DEV/PSScanner

标签: multithreadingpowershellsynchronizedcollection

解决方案


我最终解决了这个问题。

我正在调用存储在同步哈希表中的脚本块:$syncHash.Output,它将输出字符串发送到并发队列。该脚本块导致输出混乱,工作线程意外终止。直接将数据入队后,而不是调用脚本块,问题解决了。

另外,我有一个 IP 计数器 $syncHash.Count。我认为它应该是线程安全的,因为它存储在同步哈希表中,但实际上并非如此。我每次都得到不准确的计数。设置互斥锁来保护计数器变量后,它可以完美运行。我在想的唯一原因是计数器在 PSParallel 实例(Invoke-Parallel cmdlet)的工作线程中更新。不确定它如何处理哈希表。

谢谢大家的帮助。


推荐阅读