以下示例代码段实现了async
多任务处理功能,即:在线读取股票价格列表(特别是对应道琼斯工业平均指数)并将其异步存储在3个{{1} {{1} }:
Collection.Generics
Dictionary<string,double>
和
SortedDictionary<string,double>
。
该应用程序已经过测试,所有3个Generics似乎都能正常运行,而且到目前为止没有出现任何并发(竞赛条件)问题。
我的问题:即使快速测试产生了所有积极的结果,在这种类型的{{1}中使用ConcurrentDictionary<string,double>
或Dictionary<string,double>
是否安全?多任务WPF实现,还是需要使用SortedDictionary<string,double>
以避免可能的并发/竞争条件问题?
重要:为了更加清晰,请注意此问题特定于async/await
多任务实施(不仅仅是一般的TPL内容)。例如,在ConcurrentDictionary<string,double>
实现中,完全可以直接访问任何UI控件(例如async/await
)而不会出现并发/竞争问题的风险。我假设同样的考虑因素也适用于Windows类变量(特别是任何Generics数据结构,如本示例中使用的字典),使得以相同的方式使用它们是安全的,而无需额外的线程同步/ interlocking(即使常规的Collections / Dictionary本身不是线程安全的,但await
可能会处理同步问题)。
清单1.通过多个TextBox
任务
await
答案 0 :(得分:2)
Dictionary
和SortedDictionary
不是线程安全的。如果任何一个实例可以被任何线程与另一个使用它的线程同时修改,那么你必须同步。否则,你不需要。
在您的示例中,await
的每次使用都在UI线程的上下文中,因此await
之后的延续(即每个await
之后出现的代码)将继续使用也出现在UI线程中。这意味着每个集合实例仅在UI线程中使用,因此修改和访问必然不会同时发生。它们通过使用await
来序列化,以在单个线程中执行延续代码。
答案 1 :(得分:0)
如果同时使用,我肯定会使用ConcurrentDictionary
。你可以无数次地测试并获得积极的结果,然后在100或1000次中它会做一些不可预测的事情。 通常的工作实际上是一个问题,因为当它不存在时,你将无法重现错误。
Here's a thread。我做了一个并发操作的简单示例,有时我可以运行它一百次而没有任何问题。情景略有不同(它涉及序列。)但潜在的概念仍然是相同的。我处理大部分时间运行的生产应用程序,然后因为类似的问题而每隔一周锁定或行为不端。
答案 2 :(得分:0)
来自MSDN
字典可以同时支持多个读者, 只要集合没有被修改。即便如此,列举 通过集合本质上 不 是线程安全的 程序。在极少数情况下,枚举与写入竞争 访问时,必须在整个枚举期间锁定集合。 要允许多个线程访问集合以进行读写,您必须实现自己的同步。
ConcurrentDictionary<TKey,TValue>
是通用Dictionary<TKey, TValue>
集合的线程安全副本,两者都是为O(1)
设计的 - 基于密钥查找数据。
在genral中,当我们需要一个concurrent
字典时,我们正在交错读取和更新。它实现了thread-safety
,没有共同锁定来提高效率。它实际上使用一系列锁来提供并发更新,并且具有lockless
个读取。
最后但并非最不重要的,SortedDictionary
,IDictionary
的已排序实现,它们存储为有序树。虽然这些并不像未排序的词典那么快 - 它们是O(log2 n)
速度和排序的组合。