Recently in the work of doing app development under Windows Runtime. After the service layer request is returned, the UI update data is often notified through a callback. A foreach throw exception often occurs with multiple threading operations: System.InvalidOperationException: The collection has been modified, and the enumeration operation may not be performed, causing the app to crash.
Search on the Internet for a moment, the following conclusions are drawn:
- It is difficult to implement a truly thread-safe list, which can be referenced in this article why is the thread safe collections?
- Using concurrentbag<t>, Microsoft gives a set of thread-safe, the disadvantage is unordered. If the collection relies on the order of the inner elements, it is not appropriate.
- Implementing a list that enumerates security requires a relatively small amount of work, even adding lock to the list operation that was used.
The following is a minimized implementation of the enumeration security list. Because a collection that requires enumeration security is used only for operations such as Add,count, indexes, and so on, the IEnumerable interface is inherited, not IList. It also does not affect the use of LINQ to Objects extension methods, really stole a big lazy.
classEnumerationsafelist<t>: ienumerable<t> { PrivateList<t> innerlist =NewList<t>(); Private ObjectLockObject =New Object(); PublicIenumerator<t>GetEnumerator () {returnClone (). GetEnumerator (); } IEnumerator Ienumerable.getenumerator () {returnClone (). GetEnumerator (); } Public voidAdd (T item) {Lock(lockobject) {Innerlist.add (item); } } Public voidRemove (T item) {Lock(lockobject) {innerlist.remove (item); } } Public intCount {Get { Lock(lockobject) {returnInnerlist.count; } } } PublicT This[intIndex] { Get { Lock(lockobject) {returnInnerlist[index]; } } Set { Lock(lockobject) {Innerlist[index]=value; } } } PrivateList<t>Clone () {varClonelist =NewList<t>(); Lock(lockobject) {foreach(varIteminchinnerlist) {Clonelist.add (item); } } returnclonelist; } }
The code adds lock to Add,remove,count and index four operations, while at enumeration time by adding lock and returning a copy of the current collection to avoid throwing exceptions because of modifications by other threads.
If the code requires all methods of the list type, it needs to be further modified to change the IEnumerable to IList and implement the interface so that a complete "Data thread safe list" can be obtained.
Complete code and test procedures: code
Multithreaded enumeration of secure lists