【问题标题】:Powershell synchronized hash table thread safetyPowershell 同步哈希表线程安全
【发布时间】:2021-04-17 12:48:16
【问题描述】:

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

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

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

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

【问题讨论】:

  • 请创建一个minimal reproducible example 并将其(作为代码)添加到问题中。
  • 我猜线程安全 queue 是非常具体的,请参阅:C++11 thread-safe queue
  • 谢谢,艾朗。我刚刚又看了一遍文档@docs.microsoft.com/en-us/dotnet/api/…
  • 为了确定集合是否包含任何项目,建议使用此属性,而不是从 Count 属性中检索项目数并将其与 0 进行比较。但是,由于此集合旨在被访问同时,可能会出现 IsEmpty 返回后另一个线程会修改集合,从而使结果无效的情况..
  • 我已将 if 语句更改为 if(!($syncHash.Q.IsEmpty)){}。希望我不会再遇到这个错误。

标签: multithreading powershell synchronizedcollection


【解决方案1】:

我最终解决了这个问题。

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

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

感谢大家的帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-05
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    • 2012-11-12
    • 1970-01-01
    相关资源
    最近更新 更多