By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,198 Members | 916 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,198 IT Pros & Developers. It's quick & easy.

ArrayList in Thread question

P: n/a
I am using VB.NET 2003 and a socket control to receive and sending data to
clients.
As I receive data in 1 thread, I put it into an arraylist, and then I remove
the data from arraylist and send it to the client.
Before adding data to the arraylist, I check if the depth of the arraylist
is longer than iMaxQueueDepth, and if it is, I clear the arraylist.
Is it possible that while I am clearing the arraylist, the ThreadMain at the
same time also trying to remove the data in the arraylist ?
In other words, in the following codes, in the Sub NewQuote doing
QuotesSync.Add(Message) at the same time ThreadMain doing
sPacket = QuotesSync(0)
QuotesSync.RemoveAt(0)
?

Thank you.

Public Class ListenerClass
ClientSession = New SessionClass
' Create a new worker thread to handle the client session
ClientThread = New Threading.Thread(AddressOf ClientSession.ThreadMain)
end class

Public Class frmQuoteServer
Public Function RegisterClient(ByRef Session As SessionClass, ByRef Thread
As Threading.Thread) As Boolean
ReDim Preserve Client(LastClient)
client(LastClient).Session = Session
Client(LastClient).Thread = Thread
end Function

Sub ProcessEachMessage
'This sub is called by another thread that receives quotes
For lIndex = 0 To LastClient - 1
'assigning the quote to the client session
Client(lIndex).Session.NewQuote(sStr)
next
end sub
end Class

Public Class SessionClass
Public Server As frmQuoteServer
Private Quotes As New ArrayList
Private QuotesSync As ArrayList = ArrayList.Synchronized(Quotes)

Sub NewQuote(ByVal Message As String)
'this sub is called a receiving data thread receives data
If QuotesSync.Count iMaxQueueDepth Then QuotesSync.Clear() 'clear the
queue if it is longer than iMaxQueueDepth
QuotesSync.Add(Message)
end Sub

Public Sub ThreadMain()
If Server.RegisterClient(Me, Thread.CurrentThread()) = False Then
:
Exit Sub
End If

'this client thread is looping all the time until it is terminated
Do While Not Terminated
sPacket = ""
While QuotesSync.Count 0 And Not (Terminated)
sPacket = QuotesSync(0)
nResult = Socket.Write(sPacket)
QuotesSync.RemoveAt(0)
End While
Thread.Sleep(1)
Loop
end Sub
end class
Jan 6 '07 #1
Share this Question
Share on Google+
6 Replies


P: n/a
Thank you for your reply.
Do I understand it correctly that when I synchronized an arraylist, it will
be thread safe and it won't throw an exception even when other threads
modify the arraylist, but when I synchronized a collection it will still
throw an exception ?

"Kerry Moorman" <Ke**********@discussions.microsoft.comwrote in message
news:0C**********************************@microsof t.com...
fniles,

Have you noticed that the Help system always has information about a
class's
thread safety as some of the very first information about the class?

Here is the help information about thread safety for an arraylist:

Thread Safety
Public static (Shared in Visual Basic) members of this type are safe for
multithreaded operations. Instance members are not guaranteed to be
thread-safe.

An ArrayList can support multiple readers concurrently, as long as the
collection is not modified. To guarantee the thread safety of the
ArrayList,
all operations must be done through the wrapper returned by the
Synchronized
method.

Enumerating through a collection is intrinsically not a thread-safe
procedure. Even when a collection is synchronized, other threads could
still
modify the collection, which causes the enumerator to throw an exception.
To
guarantee thread safety during enumeration, you can either lock the
collection during the entire enumeration or catch the exceptions resulting
from changes made by other threads.

Kerry Moorman
"fniles" wrote:
>I am using VB.NET 2003 and a socket control to receive and sending data
to
clients.
As I receive data in 1 thread, I put it into an arraylist, and then I
remove
the data from arraylist and send it to the client.
Before adding data to the arraylist, I check if the depth of the
arraylist
is longer than iMaxQueueDepth, and if it is, I clear the arraylist.
Is it possible that while I am clearing the arraylist, the ThreadMain at
the
same time also trying to remove the data in the arraylist ?
In other words, in the following codes, in the Sub NewQuote doing
QuotesSync.Add(Message) at the same time ThreadMain doing
sPacket = QuotesSync(0)
QuotesSync.RemoveAt(0)
?

Thank you.

Public Class ListenerClass
ClientSession = New SessionClass
' Create a new worker thread to handle the client session
ClientThread = New Threading.Thread(AddressOf ClientSession.ThreadMain)
end class

Public Class frmQuoteServer
Public Function RegisterClient(ByRef Session As SessionClass, ByRef
Thread
As Threading.Thread) As Boolean
ReDim Preserve Client(LastClient)
client(LastClient).Session = Session
Client(LastClient).Thread = Thread
end Function

Sub ProcessEachMessage
'This sub is called by another thread that receives quotes
For lIndex = 0 To LastClient - 1
'assigning the quote to the client session
Client(lIndex).Session.NewQuote(sStr)
next
end sub
end Class

Public Class SessionClass
Public Server As frmQuoteServer
Private Quotes As New ArrayList
Private QuotesSync As ArrayList = ArrayList.Synchronized(Quotes)

Sub NewQuote(ByVal Message As String)
'this sub is called a receiving data thread receives data
If QuotesSync.Count iMaxQueueDepth Then QuotesSync.Clear() 'clear
the
queue if it is longer than iMaxQueueDepth
QuotesSync.Add(Message)
end Sub

Public Sub ThreadMain()
If Server.RegisterClient(Me, Thread.CurrentThread()) = False Then
:
Exit Sub
End If

'this client thread is looping all the time until it is terminated
Do While Not Terminated
sPacket = ""
While QuotesSync.Count 0 And Not (Terminated)
sPacket = QuotesSync(0)
nResult = Socket.Write(sPacket)
QuotesSync.RemoveAt(0)
End While
Thread.Sleep(1)
Loop
end Sub
end class

Jan 6 '07 #2

P: n/a
fniles,

Here the documentation is using the term "collection" to refer to all
collections, including arraylist collections.

Kerry Moorman
"fniles" wrote:
Thank you for your reply.
Do I understand it correctly that when I synchronized an arraylist, it will
be thread safe and it won't throw an exception even when other threads
modify the arraylist, but when I synchronized a collection it will still
throw an exception ?

"Kerry Moorman" <Ke**********@discussions.microsoft.comwrote in message
news:0C**********************************@microsof t.com...
fniles,

Have you noticed that the Help system always has information about a
class's
thread safety as some of the very first information about the class?

Here is the help information about thread safety for an arraylist:

Thread Safety
Public static (Shared in Visual Basic) members of this type are safe for
multithreaded operations. Instance members are not guaranteed to be
thread-safe.

An ArrayList can support multiple readers concurrently, as long as the
collection is not modified. To guarantee the thread safety of the
ArrayList,
all operations must be done through the wrapper returned by the
Synchronized
method.

Enumerating through a collection is intrinsically not a thread-safe
procedure. Even when a collection is synchronized, other threads could
still
modify the collection, which causes the enumerator to throw an exception.
To
guarantee thread safety during enumeration, you can either lock the
collection during the entire enumeration or catch the exceptions resulting
from changes made by other threads.

Kerry Moorman
"fniles" wrote:
I am using VB.NET 2003 and a socket control to receive and sending data
to
clients.
As I receive data in 1 thread, I put it into an arraylist, and then I
remove
the data from arraylist and send it to the client.
Before adding data to the arraylist, I check if the depth of the
arraylist
is longer than iMaxQueueDepth, and if it is, I clear the arraylist.
Is it possible that while I am clearing the arraylist, the ThreadMain at
the
same time also trying to remove the data in the arraylist ?
In other words, in the following codes, in the Sub NewQuote doing
QuotesSync.Add(Message) at the same time ThreadMain doing
sPacket = QuotesSync(0)
QuotesSync.RemoveAt(0)
?

Thank you.

Public Class ListenerClass
ClientSession = New SessionClass
' Create a new worker thread to handle the client session
ClientThread = New Threading.Thread(AddressOf ClientSession.ThreadMain)
end class

Public Class frmQuoteServer
Public Function RegisterClient(ByRef Session As SessionClass, ByRef
Thread
As Threading.Thread) As Boolean
ReDim Preserve Client(LastClient)
client(LastClient).Session = Session
Client(LastClient).Thread = Thread
end Function

Sub ProcessEachMessage
'This sub is called by another thread that receives quotes
For lIndex = 0 To LastClient - 1
'assigning the quote to the client session
Client(lIndex).Session.NewQuote(sStr)
next
end sub
end Class

Public Class SessionClass
Public Server As frmQuoteServer
Private Quotes As New ArrayList
Private QuotesSync As ArrayList = ArrayList.Synchronized(Quotes)

Sub NewQuote(ByVal Message As String)
'this sub is called a receiving data thread receives data
If QuotesSync.Count iMaxQueueDepth Then QuotesSync.Clear() 'clear
the
queue if it is longer than iMaxQueueDepth
QuotesSync.Add(Message)
end Sub

Public Sub ThreadMain()
If Server.RegisterClient(Me, Thread.CurrentThread()) = False Then
:
Exit Sub
End If

'this client thread is looping all the time until it is terminated
Do While Not Terminated
sPacket = ""
While QuotesSync.Count 0 And Not (Terminated)
sPacket = QuotesSync(0)
nResult = Socket.Write(sPacket)
QuotesSync.RemoveAt(0)
End While
Thread.Sleep(1)
Loop
end Sub
end class


Jan 6 '07 #3

P: n/a
THanks.
To guarantee thread safety during enumeration, you can either lock the
collection during the entire enumeration or catch the exceptions
resulting
from changes made by other threads.
If I lock the arraylist, and another thread try to modify it, what will
happen there ?

"Kerry Moorman" <Ke**********@discussions.microsoft.comwrote in message
news:AE**********************************@microsof t.com...
fniles,

Here the documentation is using the term "collection" to refer to all
collections, including arraylist collections.

Kerry Moorman
"fniles" wrote:
>Thank you for your reply.
Do I understand it correctly that when I synchronized an arraylist, it
will
be thread safe and it won't throw an exception even when other threads
modify the arraylist, but when I synchronized a collection it will still
throw an exception ?

"Kerry Moorman" <Ke**********@discussions.microsoft.comwrote in message
news:0C**********************************@microso ft.com...
fniles,

Have you noticed that the Help system always has information about a
class's
thread safety as some of the very first information about the class?

Here is the help information about thread safety for an arraylist:

Thread Safety
Public static (Shared in Visual Basic) members of this type are safe
for
multithreaded operations. Instance members are not guaranteed to be
thread-safe.

An ArrayList can support multiple readers concurrently, as long as the
collection is not modified. To guarantee the thread safety of the
ArrayList,
all operations must be done through the wrapper returned by the
Synchronized
method.

Enumerating through a collection is intrinsically not a thread-safe
procedure. Even when a collection is synchronized, other threads could
still
modify the collection, which causes the enumerator to throw an
exception.
To
guarantee thread safety during enumeration, you can either lock the
collection during the entire enumeration or catch the exceptions
resulting
from changes made by other threads.

Kerry Moorman
"fniles" wrote:

I am using VB.NET 2003 and a socket control to receive and sending
data
to
clients.
As I receive data in 1 thread, I put it into an arraylist, and then I
remove
the data from arraylist and send it to the client.
Before adding data to the arraylist, I check if the depth of the
arraylist
is longer than iMaxQueueDepth, and if it is, I clear the arraylist.
Is it possible that while I am clearing the arraylist, the ThreadMain
at
the
same time also trying to remove the data in the arraylist ?
In other words, in the following codes, in the Sub NewQuote doing
QuotesSync.Add(Message) at the same time ThreadMain doing
sPacket = QuotesSync(0)
QuotesSync.RemoveAt(0)
?

Thank you.

Public Class ListenerClass
ClientSession = New SessionClass
' Create a new worker thread to handle the client session
ClientThread = New Threading.Thread(AddressOf
ClientSession.ThreadMain)
end class

Public Class frmQuoteServer
Public Function RegisterClient(ByRef Session As SessionClass, ByRef
Thread
As Threading.Thread) As Boolean
ReDim Preserve Client(LastClient)
client(LastClient).Session = Session
Client(LastClient).Thread = Thread
end Function

Sub ProcessEachMessage
'This sub is called by another thread that receives quotes
For lIndex = 0 To LastClient - 1
'assigning the quote to the client session
Client(lIndex).Session.NewQuote(sStr)
next
end sub
end Class

Public Class SessionClass
Public Server As frmQuoteServer
Private Quotes As New ArrayList
Private QuotesSync As ArrayList = ArrayList.Synchronized(Quotes)

Sub NewQuote(ByVal Message As String)
'this sub is called a receiving data thread receives data
If QuotesSync.Count iMaxQueueDepth Then QuotesSync.Clear() 'clear
the
queue if it is longer than iMaxQueueDepth
QuotesSync.Add(Message)
end Sub

Public Sub ThreadMain()
If Server.RegisterClient(Me, Thread.CurrentThread()) = False Then
:
Exit Sub
End If

'this client thread is looping all the time until it is terminated
Do While Not Terminated
sPacket = ""
While QuotesSync.Count 0 And Not (Terminated)
sPacket = QuotesSync(0)
nResult = Socket.Write(sPacket)
QuotesSync.RemoveAt(0)
End While
Thread.Sleep(1)
Loop
end Sub
end class



Jan 6 '07 #4

P: n/a
On 2007-01-06, fniles <fn****@pfmail.comwrote:
THanks.
>To guarantee thread safety during enumeration, you can either lock the
collection during the entire enumeration or catch the exceptions
resulting
from changes made by other threads.
If I lock the arraylist, and another thread try to modify it, what will
happen there ?
There are a lot of issues with threading and collections. You have to be very
careful - even with a syncronized wrapper. The fact, is that lots of stuff
can happen in a multi-threaded program in orders that you do not intend.. for
example:

sub somesub ' run on a thread
arraylist.clear ()
end sub
function acoolfunction 'run on a different thread
if arraylist.count 0
return arraylist(0)
end if
end function

hmmm, this is a syncronized collection, but the problem is that it is only
syncronized between calls to it's methods - so what happens if you get this
order of execution:

'arraylist starts with count 10
function acoolfunction
if arraylist.count 0

---- Task switch

sub somesub
arraylist.clear()

--- Task Switch

return arraylist(0) ' BIG FAT EXCEPTION

See, in these kinds of operations, you really need something like an sql
transaction - to treat multiple operations as atomic. You achieve that using
the synclock statement (or some other locking mechanism, such as
system.threading.monitor). This is refered to as a "critical section". Then
the code would look something like:

sub somesub ' run on a thread
synclock arraylist.syncroot
arraylist.clear()
end synclock
end sub

function acoolfunction ' run on a different thread
synclock arraylist.syncroot ' lock the arraylist
if arraylist.count 0
return arraylist(0)
endif
end synclock
end function

Now those blocks of code can not be entered at the same time... This makes
sure that the execution scenario from my example does not occur. All requests
will be queued, until the end of the synclock block... Make sense? Also, be
aware that the object you lock on needs to be the same for all the sync'd
operations and it must be a reference type. You can pass in a value, type and
you won't get a compiler error - you code just won't be thread safe. This is
because synclock expects the sync object to be of type object - if you pass in
say an integer value, then it will be boxed - but the object wrapper will be
different in each block of code.

I find most of the operations I do are like the above and involve multiple calls
to the collection, so I very seldom use the syncronized wrapper - that just
adds extra locking overhead for every call. So, I tend to use code similar to
the above, which does basically the same thing except over mutlipe calls.

Watch out for deadlocks, etc. Multi-threaded code is very hard to get right,
so be prepared for problems :) I have done quite a bit of multi-threaded code
over the last couple of years - and I still don't feel I'm anywhere near an
expert at it...

--
Tom Shelton
Jan 6 '07 #5

P: n/a
Thank you very much for your reply.

I have a few more questions.
1. In your example using the synclock statement, did you mean that you use
arraylist and not the syncronized arraylist with the synclock ?
2. >Also, be aware that the object you lock on needs to be the same for all
the sync'd operations and it must be a reference type.
In my program I did not pass in the parameter. The arraylist and its
syncronized arraylist are in the class like the following:
Private Quotes As New ArrayList
Private QuotesSync As ArrayList = ArrayList.Synchronized(Quotes)
3. Can I simply trap the exception when it happen like the following ?
sub somesub ' run on a thread
try
arraylist.clear ()
Catch ex As Exception
End Try
end sub

function acoolfunction 'run on a different thread
if arraylist.count 0
try
return arraylist(0)
Catch ex As Exception
End Try
end if
end function

4. What can I do when deadlocks happens ?

"Tom Shelton" <to*********@comcastXXXXXXX.netwrote in message
news:6d******************************@comcast.com. ..
On 2007-01-06, fniles <fn****@pfmail.comwrote:
>THanks.
>>To guarantee thread safety during enumeration, you can either lock
the
collection during the entire enumeration or catch the exceptions
resulting
from changes made by other threads.
If I lock the arraylist, and another thread try to modify it, what will
happen there ?

There are a lot of issues with threading and collections. You have to be
very
careful - even with a syncronized wrapper. The fact, is that lots of
stuff
can happen in a multi-threaded program in orders that you do not intend..
for
example:

sub somesub ' run on a thread
arraylist.clear ()
end sub
function acoolfunction 'run on a different thread
if arraylist.count 0return arraylist(0)
end if
end function

hmmm, this is a syncronized collection, but the problem is that it is only
syncronized between calls to it's methods - so what happens if you get
this
order of execution:

'arraylist starts with count 10
function acoolfunction
if arraylist.count 0

---- Task switch

sub somesub
arraylist.clear()

--- Task Switch

return arraylist(0) ' BIG FAT EXCEPTION

See, in these kinds of operations, you really need something like an sql
transaction - to treat multiple operations as atomic. You achieve that
using
the synclock statement (or some other locking mechanism, such as
system.threading.monitor). This is refered to as a "critical section".
Then
the code would look something like:

sub somesub ' run on a thread
synclock arraylist.syncroot
arraylist.clear()
end synclock
end sub

function acoolfunction ' run on a different thread
synclock arraylist.syncroot ' lock the arraylist
if arraylist.count 0
return arraylist(0)
endif
end synclock
end function

Now those blocks of code can not be entered at the same time... This
makes
sure that the execution scenario from my example does not occur. All
requests
will be queued, until the end of the synclock block... Make sense? Also,
be
aware that the object you lock on needs to be the same for all the sync'd
operations and it must be a reference type. You can pass in a value, type
and
you won't get a compiler error - you code just won't be thread safe. This
is
because synclock expects the sync object to be of type object - if you
pass in
say an integer value, then it will be boxed - but the object wrapper will
be
different in each block of code.

I find most of the operations I do are like the above and involve multiple
calls
to the collection, so I very seldom use the syncronized wrapper - that
just
adds extra locking overhead for every call. So, I tend to use code
similar to
the above, which does basically the same thing except over mutlipe calls.

Watch out for deadlocks, etc. Multi-threaded code is very hard to get
right,
so be prepared for problems :) I have done quite a bit of multi-threaded
code
over the last couple of years - and I still don't feel I'm anywhere near
an
expert at it...

--
Tom Shelton

Jan 7 '07 #6

P: n/a
On 2007-01-07, fniles <fn****@pfmail.comwrote:
Thank you very much for your reply.

I have a few more questions.
1. In your example using the synclock statement, did you mean that you use
arraylist and not the syncronized arraylist with the synclock ?
I generally don't use a sync'd arraylist. Simply because it is rare that I
use atomic operations, generally I want to do stuff like in my acoolfunction -
do a test and an operation. The sync'd arraylist won't do anything for you in
these cases - except add the extra locking overhead. So, I generally just use
the arraylist with it's syncroot property.
2. >Also, be aware that the object you lock on needs to be the same for all
the sync'd operations and it must be a reference type.
In my program I did not pass in the parameter. The arraylist and its
syncronized arraylist are in the class like the following:
Private Quotes As New ArrayList
Private QuotesSync As ArrayList = ArrayList.Synchronized(Quotes)
That's fine. My code was psuedo code. So, in your case:

SyncLock Me.Quotes.SyncRoot
' do cool stuff with quotes
End SyncLock

You just need to make sure that all the methods you are syncronizing are using
the same reference.
3. Can I simply trap the exception when it happen like the following ?
sub somesub ' run on a thread
try
arraylist.clear ()
Catch ex As Exception
End Try
end sub

function acoolfunction 'run on a different thread
if arraylist.count 0
try
return arraylist(0)
Catch ex As Exception
End Try
end if
end function
Sure. You could trap the exception. The point of the example was to show
what might happen... You just need to be aware that in a multi-threaded
application you can not be sure of your order of execution - so in some cases
you need to introduce locking to ensure that bad things don't happen.
4. What can I do when deadlocks happens ?
Not a lot :) The thing to do with deadlocks is to make sure they don't
happen. There are lots of techniques on the web for doing so. One is using a
timed lock. There is a discussion of this technique at:

http://www.interact-sw.co.uk/iangblo.../03/23/locking

The code is C#, but this would apply in VB.NET as well.

There are other techniques for prevention and detection of deadlocks - but
that is a very advanced topic. One that I myself am still exploring. Like I
said, I'm far from an expert on this topic - even though I've done lots of it
over the last two to three years :)

--
Tom Shelton
Jan 7 '07 #7

This discussion thread is closed

Replies have been disabled for this discussion.