Threading Issue with ArrayList

  • Thread starter Thread starter Eric
  • Start date Start date
E

Eric

I'm looking at this page in the MSDN right here:
ms-help://MS.MSDNQTR.2003FEB.1033/cpref/html/frlrfsystemcollectionsarraylist
classsynchronizedtopic2.htm

(or online here:
http://msdn.microsoft.com/library/d...mcollectionsicollectionclasssyncroottopic.asp)

And I'm interested in locking an ArrayList during the entire enumeration, as
shown in the example code. My problem is that I'm STILL getting "Collection
was modified; enumeration operation may not execute" error messages from
InvalidOperationException during enumeration. I have no doubt that another
thread is removing items from the list as I read them, but this page in the
MSDN leads me to believe that I can prevent that from happening while I'm
still enumerating.

My ArrayList has a synchronized wrapper declared like this:
protected static ArrayList nodes = ArrayList.Synchronized(new ArrayList());

I am enumerating through the list with "foreach" which normally would be a
very bad idea, but as in the example code, I have enclosed the entire
operation in lock (nodes.SyncRoot) { } ... So what am I doing wrong?

Thanks so much in advance.
 
Thanks for the quick response and the amount of effort you put into it. I
really appreciate it.

Code within my enumeration loop is sending a message object via an event to
another thread. This message object is to be interpreted by the target
thread and instructs the target thread to remove items from the ArrayList.
So, my enumeration loop is indirectly responsible for removing collection
items from the list (or at least that is the effect I was trying to
achieve.)

Shouldn't this be ok? Just to make sure I was delegating responsibility
correctly (making sure the calling thread wasn't directly responsible for
the item removal), I suspended the calling thread and the target thread
still carried out the event handling as planned after the message object was
received.

These aren't worker threads, they are socket threads in a socket server
where each thread represents a connected client. Everything else seems to be
working perfectly, and if I replace "foreach" with a while loop, it works
fine. But I really rather understand this than use a workaround.

Thanks again for your help.

Nicholas Paldino said:
Eric,

If you are locking on the object returned by the SyncRoot property, then
you should not be able Add/Remove objects until the lock is released (I've
attached a small console app that shows this works). Because of this, I
would suspect that something that you are calling in your loop is modifying
the contents.

Can you show the code in your loop (as well as the lock statement
outside of your loop).

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


Eric said:
I'm looking at this page in the MSDN right here:
ms-help://MS.MSDNQTR.2003FEB.1033/cpref/html/frlrfsystemcollectionsarraylist
classsynchronizedtopic2.htm

(or online here:
http://msdn.microsoft.com/library/d...mcollectionsicollectionclasssyncroottopic.asp)
And I'm interested in locking an ArrayList during the entire
enumeration,
as
shown in the example code. My problem is that I'm STILL getting "Collection
was modified; enumeration operation may not execute" error messages from
InvalidOperationException during enumeration. I have no doubt that another
thread is removing items from the list as I read them, but this page in the
MSDN leads me to believe that I can prevent that from happening while I'm
still enumerating.

My ArrayList has a synchronized wrapper declared like this:
protected static ArrayList nodes = ArrayList.Synchronized(new ArrayList());

I am enumerating through the list with "foreach" which normally would be a
very bad idea, but as in the example code, I have enclosed the entire
operation in lock (nodes.SyncRoot) { } ... So what am I doing wrong?

Thanks so much in advance.
 
Are other methods that also make use of the ArrayList locking on the
SyncRoot property as well? Everything that would be accessing the ArrayList
and potentially adding or removing elements from it should be using the same
lock method, to ensure that the lock is properly handled. If you have one
method that is locking on the SyncRoot, and another method in another thread
that is just adding or removing elements at will without checking for the
lock, then you're going to run into problems.

Ryan Gregg



Eric said:
Thanks for the quick response and the amount of effort you put into it. I
really appreciate it.

Code within my enumeration loop is sending a message object via an event to
another thread. This message object is to be interpreted by the target
thread and instructs the target thread to remove items from the ArrayList.
So, my enumeration loop is indirectly responsible for removing collection
items from the list (or at least that is the effect I was trying to
achieve.)

Shouldn't this be ok? Just to make sure I was delegating responsibility
correctly (making sure the calling thread wasn't directly responsible for
the item removal), I suspended the calling thread and the target thread
still carried out the event handling as planned after the message object was
received.

These aren't worker threads, they are socket threads in a socket server
where each thread represents a connected client. Everything else seems to be
working perfectly, and if I replace "foreach" with a while loop, it works
fine. But I really rather understand this than use a workaround.

Thanks again for your help.

message news:[email protected]...
Eric,

If you are locking on the object returned by the SyncRoot property, then
you should not be able Add/Remove objects until the lock is released (I've
attached a small console app that shows this works). Because of this, I
would suspect that something that you are calling in your loop is modifying
the contents.

Can you show the code in your loop (as well as the lock statement
outside of your loop).

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


Eric said:
I'm looking at this page in the MSDN right here:
ms-help://MS.MSDNQTR.2003FEB.1033/cpref/html/frlrfsystemcollectionsarraylisthttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemcollectionsicollectionclasssyncroottopic.asp)
enumeration, in
the
be
 
Ooops. I misinterpreted something. I see my mistake now. The target thread
(that receives the event) is NOT taking over after it receives the message
object. How can I have a thread that receives an event take over after the
event has been triggered? It appears as if the calling thread is actually
directly responsible for the item removal (and more). I wanted to keep the
threads as isolated as possible and only send messages between them for
signaling without using a true messaging/queue system.

Sorry for the confusion. I am coming from a Delphi background and trying to
understand threads in .NET.
 
I understand my problem clearly now; I would like to fire events across
threads. When an event is triggered, the calling thread is the one
responsible for executing code within the handler. I solved this easily by
using Invoke/BeginInvoke when working with Windows forms, but this
application has no forms at all. Is there an equivalent of
Invoke/BeginInvoke somewhere within the System.Threading namespace or
something of the sort?
 
Ryan,

The OP indicated that the array list was obtained from the static
Synchronized method, so all calls to the ArrayList (Add, Remove, etc, etc)
lock around it in the implementation.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Ryan Gregg said:
Are other methods that also make use of the ArrayList locking on the
SyncRoot property as well? Everything that would be accessing the ArrayList
and potentially adding or removing elements from it should be using the same
lock method, to ensure that the lock is properly handled. If you have one
method that is locking on the SyncRoot, and another method in another thread
that is just adding or removing elements at will without checking for the
lock, then you're going to run into problems.

Ryan Gregg



Eric said:
Thanks for the quick response and the amount of effort you put into it. I
really appreciate it.

Code within my enumeration loop is sending a message object via an event to
another thread. This message object is to be interpreted by the target
thread and instructs the target thread to remove items from the ArrayList.
So, my enumeration loop is indirectly responsible for removing collection
items from the list (or at least that is the effect I was trying to
achieve.)

Shouldn't this be ok? Just to make sure I was delegating responsibility
correctly (making sure the calling thread wasn't directly responsible for
the item removal), I suspended the calling thread and the target thread
still carried out the event handling as planned after the message object was
received.

These aren't worker threads, they are socket threads in a socket server
where each thread represents a connected client. Everything else seems
to
be
working perfectly, and if I replace "foreach" with a while loop, it works
fine. But I really rather understand this than use a workaround.

Thanks again for your help.

message news:[email protected]...
Eric,

If you are locking on the object returned by the SyncRoot
property,
then
you should not be able Add/Remove objects until the lock is released (I've
attached a small console app that shows this works). Because of this, I
would suspect that something that you are calling in your loop is modifying
the contents.

Can you show the code in your loop (as well as the lock statement
outside of your loop).

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


I'm looking at this page in the MSDN right here:
ms-help://MS.MSDNQTR.2003FEB.1033/cpref/html/frlrfsystemcollectionsarraylisthttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemcollectionsicollectionclasssyncroottopic.asp)
while
I'm
would
 
Not exactly, the Invoke / BeginInvoke methods on winform controls
actually post messages to the UI message pump.
If you are looking to signal another thread, perhaps you could use
AutoResetEvent or ManualResetEvent in System.Threading.

HTH,
 
AutoResetEvent or ManualResetEvent would be good, but I can't block the
thread waiting until a message is received. All threads operate
independently and simultaneously and must execute continuously. A message
could come at any time, it isn't planned or predictable so I can't wait
around for it. In the meantime, the thread is servicing user requests from
the connected sockets.
 
You don't have to block, by using a WaitXXX method with a zero timespan and
then watch the return value. This becomes a polling pattern, which assumes
you have some loop of code in which to do the polling.

Brad Williams
 
You're right. I was just reading too fast!

Ryan Gregg


Nicholas Paldino said:
Ryan,

The OP indicated that the array list was obtained from the static
Synchronized method, so all calls to the ArrayList (Add, Remove, etc, etc)
lock around it in the implementation.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Ryan Gregg said:
Are other methods that also make use of the ArrayList locking on the
SyncRoot property as well? Everything that would be accessing the ArrayList
and potentially adding or removing elements from it should be using the same
lock method, to ensure that the lock is properly handled. If you have one
method that is locking on the SyncRoot, and another method in another thread
that is just adding or removing elements at will without checking for the
lock, then you're going to run into problems.

Ryan Gregg
it.
I
really appreciate it.

Code within my enumeration loop is sending a message object via an
event
to
another thread. This message object is to be interpreted by the target
thread and instructs the target thread to remove items from the ArrayList.
So, my enumeration loop is indirectly responsible for removing collection
items from the list (or at least that is the effect I was trying to
achieve.)

Shouldn't this be ok? Just to make sure I was delegating responsibility
correctly (making sure the calling thread wasn't directly responsible for
the item removal), I suspended the calling thread and the target thread
still carried out the event handling as planned after the message
object
was
received.

These aren't worker threads, they are socket threads in a socket server
where each thread represents a connected client. Everything else seems
to
be
working perfectly, and if I replace "foreach" with a while loop, it works
fine. But I really rather understand this than use a workaround.

Thanks again for your help.

"Nicholas Paldino [.NET/C# MVP]" <[email protected]>
wrote
in
message Eric,

If you are locking on the object returned by the SyncRoot property,
then
you should not be able Add/Remove objects until the lock is released (I've
attached a small console app that shows this works). Because of
this,
I
would suspect that something that you are calling in your loop is
modifying
the contents.

Can you show the code in your loop (as well as the lock statement
outside of your loop).

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


I'm looking at this page in the MSDN right here:
ms-help://MS.MSDNQTR.2003FEB.1033/cpref/html/frlrfsystemcollectionsarraylisthttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemcollectionsicollectionclasssyncroottopic.asp)
messages
from page
in would
 
Thanks to everyone who helped me with this. Especially Nicholas, Scott, and
Brad!

The older version of this app uses polling that was done within a loop that
handled socket reads and would timeout on a given interval and check for
messages during that loop. Currently, the sockets are implemenetd on a lower
level and the application itself doesn't concern itself with when the socket
read operations time out, so there is no loop in the application logic.

I could setup a messaging system again that uses polling, but I would rather
not if I could avoid it. I'd much rather have an event-triggered model where
messages are sent immediately and other threads are aware of that message
immediately rather than endlessly checking every x milliseconds. Has anyone
implemented anything like this before?

Perhaps I could implement IAsyncCallback? But that would mean a new thread
for every message sent and that seems wasteful (we're talking about a lot of
messages here).
 
Back
Top