Why My Thread Safe Generic List Collection not Respect My Enumerator ??!!!
Introduction
Enumerating through a collection is not a thread safe, Is it real ? this question is knocking my head since saw this subject in MSDN ( Link ) and subsequently more questions & ideas starts in my mind. The real question was, why shall use thread safe collection? according to Microsoft, the answer was simple, it is for better and faster performance, however my understanding is also simple; all property and methods within the generic class shall be written using SyncLock, hope I'm correct, and here it is the code..
Public Class RiverNileList(Of T)
Implements IList(Of T)
#Region " RiverNileList (of T) "
#Region " Field "
Friend _lock As Object = CType(Nothing, Object)
Friend _list As List(Of T) = CType(Nothing, List(Of T))
#End Region
#Region " Constructor "
Public Sub New()
Me.New(New Object)
End Sub
Friend Sub New(obj As Object)
Me._lock = obj
End Sub
#End Region
#Region " Property "
Public ReadOnly Property InnerList As List(Of T)
Get
SyncLock Me._lock
If Me._list Is Nothing Then
Me._list = New List(Of T)()
End If
End SyncLock
Return Me._list
End Get
End Property
Default Public Property Item(index As Integer) As T Implements IList(Of T).Item
Get
Dim value As T = CType(Nothing, T)
SyncLock Me._lock
value = Me.InnerList(index)
End SyncLock
Return value
End Get
Set(value As T)
SyncLock Me._lock
Me.InnerList(index) = value
End SyncLock
End Set
End Property
Public ReadOnly Property Count As Integer Implements ICollection(Of T).Count
Get
Dim value As Integer = CType(Nothing, Integer)
SyncLock Me._lock
value = Me.InnerList.Count
End SyncLock
Return value
End Get
End Property
Public ReadOnly Property IsReadOnly As Boolean Implements ICollection(Of T).IsReadOnly
Get
Dim value As Boolean = CType(Nothing, Boolean)
SyncLock Me._lock
value = False
End SyncLock
Return value
End Get
End Property
#End Region
#Region " Method "
Public Function Where(predicate As Func(Of T, Boolean)) As RiverNileList(Of T)
SyncLock Me._lock
Return New RiverNileList(Of T)(CType(Me._list, IEnumerable(Of T)).Where(predicate).ToList())
End SyncLock
End Function
Public Function FirstOrDefault(predicate As Func(Of T, Boolean)) As T
SyncLock Me._lock
Return CType(_list, IEnumerable(Of T)).FirstOrDefault(predicate)
End SyncLock
End Function
Public Sub AddRange(collection As IEnumerable(Of T))
SyncLock Me._lock
Me.InnerList.AddRange(collection)
End SyncLock
End Sub
Public Sub Add(item As T) Implements ICollection(Of T).Add
SyncLock Me._lock
Me.InnerList.Add(item)
End SyncLock
End Sub
Public Sub Clear() Implements ICollection(Of T).Clear
SyncLock Me._lock
Me.InnerList.Clear()
End SyncLock
End Sub
Public Function Contains(item As T) As Boolean Implements ICollection(Of T).Contains
Dim value As Boolean = CType(Nothing, Boolean)
SyncLock Me._lock
value = Me.InnerList.Contains(item)
End SyncLock
Return value
End Function
Public Sub CopyTo(array() As T, arrayIndex As Integer) Implements ICollection(Of T).CopyTo
SyncLock Me._lock
Me.InnerList.CopyTo(array, arrayIndex)
End SyncLock
End Sub
Public Sub CopyTo(array As T())
SyncLock Me._lock
Me.InnerList.CopyTo(array)
End SyncLock
End Sub
Public Function Remove(item As T) As Boolean Implements ICollection(Of T).Remove
Dim value As Boolean = CType(Nothing, Boolean)
SyncLock Me._lock
value = Me.InnerList.Remove(item)
End SyncLock
Return value
End Function
Public Function IndexOf(item As T) As Integer Implements IList(Of T).IndexOf
Dim value As Integer = CType(Nothing, Integer)
SyncLock Me._lock
value = Me.InnerList.IndexOf(item)
End SyncLock
Return value
End Function
Public Sub Insert(index As Integer, item As T) Implements IList(Of T).Insert
SyncLock Me._lock
Me.InnerList.Insert(index, item)
End SyncLock
End Sub
Public Sub RemoveAt(index As Integer) Implements IList(Of T).RemoveAt
SyncLock Me._lock
Me.InnerList.RemoveAt(index)
End SyncLock
End Sub
Public Function GetEnumerator() As IEnumerator(Of T) Implements IEnumerable(Of T).GetEnumerator
Dim value As IEnumerator(Of T) = CType(Nothing, IEnumerator(Of T))
SyncLock Me._lock
' Why My collection not respect my Enumerator.......??????????????
value = New RiverNileListEnumerator(Me)
' the collection works fine with this value
'value = Me.InnerList.GetEnumerator()
End SyncLock
Return value
End Function
Private Function GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator
Dim value As IEnumerator = CType(Nothing, IEnumerator)
SyncLock Me._lock
value = New RiverNileListEnumerator(Me)
'value = Me.InnerList.GetEnumerator()
End SyncLock
Return value
End Function
#End Region
#End Region
#Region " Enumerator "
Friend Class RiverNileListEnumerator
Implements IEnumerator(Of T)
Private _list As RiverNileList(Of T)
Private _enumerator As IEnumerator(Of T)
Public Sub New(list As RiverNileList(Of T))
SyncLock Me._list._lock
Me._list = New RiverNileList(Of T)()
Me._list.AddRange(list)
Me._enumerator = Me._list.InnerList.GetEnumerator()
End SyncLock
End Sub
Public ReadOnly Property Current As T Implements IEnumerator(Of T).Current
Get
Dim value As T = CType(Nothing, T)
SyncLock Me._list._lock
value = Me._enumerator.Current
End SyncLock
Return value
End Get
End Property
Private ReadOnly Property Current1 As Object Implements IEnumerator.Current
Get
Dim value As Object = CType(Nothing, Object)
SyncLock Me._list._lock
value = Me._enumerator.Current
End SyncLock
Return value
End Get
End Property
Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
Dim result As Boolean = CType(Nothing, Boolean)
SyncLock Me._list._lock
result = Me._enumerator.MoveNext()
End SyncLock
Return result
End Function
Public Sub Reset() Implements IEnumerator.Reset
SyncLock Me._list._lock
Me._enumerator.Reset()
End SyncLock
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
SyncLock Me._list._lock
Me._enumerator.Dispose()
End SyncLock
End Sub
End Class
#End Region
End Class ' RiverNileList(Of T)
Points of Interest
while testing the collection, I found that it is return nothing, then in the GetEnumerator Method, I made a small change and replace my Enumerator with the InnerList Enumerator and then the collection works fineto make the collection works for you, uncomment this line of code in the GetEnumerator Method.
value = Me.InnerList.GetEnumerator()
and comment this line of code in the same method
value = New RiverNileListEnumerator(Me)
In fact.....!!!!!!!!!!!!.......Just wonder
Why my Thread Safe Generic Collection Not Respect my Enumerator??!!!
After searching and reading finally get the answer to my question and my collection works great:
For Each statement shall used as follows:
Private Colors As RiverNileList(Of KnownColor) = New RiverNileList(Of KnownColor)() From {KnownColor.ActiveCaption, KnownColor.Aqua, KnownColor.YellowGreen}
For Each clr As KnownColor In Colors.ToArray()
ListBox2.Items.Add(clr)
Next
To do this properly and to remove out the lock in the ToArray
and Add
methods
guess I shall to implement ICollection
(OF T)
instead of IList(OF T)which might be not support lock
Comments
Post a Comment