VB.NET - Thread safe collections (use SyncLock or Synchronize?)

Ok this is becoming a huge pain, I can't figure out how to do this. I tried SyncLock but I must have done it wrong because I was still getting out of range exceptions.

I have a timer that fires every 1 second & loops through this collection to check some conditions... also have events that can be raised from other threads that can use / modify these collections the same way.

Here is an example of my code, how can I make this thread safe?

Dim OfficeCollection As New ArrayList

Public Structure OfficeData
    Dim firstname As String
    Dim lastname As String
End Structure

*** Timer Start
    Dim ODC As OfficeData
    ODC.firstname = "whatever"
    ODC.lastname = "whatever"

    For x = OfficeCollection.Count -1 to 0 Step -1
        ... some condition 1: OfficeCollection.Add(ODC)
        ... some condition 2: OfficeCollection.Remove(ODC)
    Next
Timer End ***

*** Event 1 Start
    Dim ODC As OfficeData
    ODC.firstname = "whatever"
    ODC.lastname = "whatever"

    For x = OfficeCollection.Count -1 to 0 Step -1
       ... conditions
        OfficeCollection.Add(ODC)
    Next
Event 1 End ***

*** Event 2 Start
    Dim ODC As OfficeData
    ODC.firstname = "whatever"
    ODC.lastname = "whatever"

    For x = OfficeCollection.Count -1 to 0 Step -1
       ... conditions
        OfficeCollection.Remove(ODC)
    Next
Event 2 End ***

I'm pretty frustrated at this point... I'm not 100% sure where to use SyncLock (around the for loop? only around .Add / .Remove calls? Both?)

What about  .Synchronize?

Thanks a ton
mcaincAsked:
Who is Participating?
 
Christopher KileConnect With a Mentor Commented:
Why reinvent the wheel? :)
Check out this previous solution and the links it provides, then if you need more help write back.
http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_23867613.html
 
0
 
mcaincAuthor Commented:
On MSDN in Thread Safety (for the ArrayList class) it says that the list is only thread safe if it isn't modified... thats where my problem is, events are modifying the list before reads have finished.

I guess I'm just not following exactly where to place these locks.. I appreciate your help, my head is mush right now :(
0
 
mcaincAuthor Commented:
** reading the list is only thread safe if it isn't modified.
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
Christopher KileCommented:
http://msdn.microsoft.com/en-us/library/system.collections.icollection.syncroot.aspx
http://msdn.microsoft.com/en-us/library/system.collections.arraylist.issynchronized.aspx
The big problem seems to be when you're enumerating while something else is modifying the collection.  
Do you want a picture of the collection at the time you modified it, and don't care what changes take place after you take the intial picture? Then lock the list, copy it to a temporary working copy of the list, then release your lock.  Modification threads can then go to work.
Do you want your list to always reflect changes to it?  Then use do-while loops and forget enumerators.  Each time you fetch an item, lock the list while you fetch the item, then release the lock as soon as the fetch is complete.  When you add an item or remove an item, include a try-catch block that handles the exceptions which occur when the item is already in the list or when it has already been removed.  Don't use for loops, as sometimes the compiler will cache the end counter in a register at the start of the loop; always use a standalone if-then to check whether your current index is greater than the size of the list.
Try playing with some of these thoughts, after you take a break.  
0
 
mcaincAuthor Commented:
my list will change frequently during loops (the list is looped through every second by a timer)... so if at all possible. I would like to always be working with a list that reflects changes to it

I haven't thought to try a do while loop

i'm still having trouble wrapping my head around the way to structure that do while loop (as far as where to lock)

        Dim x As Integer = 0
        Do While x <> MyList.Count - 1
            SyncLock MySync.SyncObject
                ODC = MyList(x)
            End SyncLock
                ' perform task & remove item from MyList if condition met?
            x = x + 1
        Loop

or

        Dim x As Integer = 0
        SyncLock MySync.SyncObject
            Do While x <> MyList.Count - 1
                ODC = MyList(x)
                ' perform task & remove item from MyList if condition met?
                x = x + 1
            Loop
        End SyncLock

or am I still way off? (sorry still green when it comes to threading)

0
 
Mike TomlinsonConnect With a Mentor Middle School Assistant TeacherCommented:
You want the second version.

Basically you need to use SyncLock around the entire looping structure and around the add/remove methods.

But just so we are clear...if implemented like this it will actually PREVENT changes completely until the looping blocks have completed.  The other threads will wait for the loops to finish before they can modify the collection.
0
 
mcaincAuthor Commented:
ok so just to confirm, my code would be something like this:

Private Sub TimerFired() - happens every 1 second
    Dim x As Integer = 0
    SyncLock MySync.SyncObject
        Do While x <> MyList.Count - 1
            ODC = MyList(x)
            ... condition 1: AddToMyList(ODC)
            ... condition 2: RemoveFromMyList(x)
            x = x + 1
        Loop
    End SyncLock
End Sub

Private Sub AddToMyList(var)
    SyncLock MySync.SyncObject
        MyList.Add(var)
    End SyncLock
End Sub

Private Sub RemoveFromMyList(index)
    SyncLock MySync.SyncObject
        MyList.RemoveAt(index)
    End SyncLock
End Sub

should this do it? thanks guys!
0
 
mcaincAuthor Commented:
one more thing... this probably sounds silly but, with the synclocks in the add/remove subs... i should be able to call those subs freely from other methods without issues right?
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
That should do it.

You can still call the add/remove subs from anywhere but remember that now that you have "synchronized" the threads you have the potential for deadlocks.  Code carefully...  =)
http://msdn.microsoft.com/en-us/library/fxy8dte8(VS.71).aspx
0
 
mcaincAuthor Commented:
oh yay, this is going to be fun

thanks guys
0
 
Christopher KileCommented:
You're very welcome :)
0
All Courses

From novice to tech pro — start learning today.