framework 1.1 & Queue class

G

Guest

Hi,

I am in need to a Queue class for a high speed read write operation where i
do not have to look the object / collection in order to add / remove items. I
had a look at System.Collections.Queue class and i need some clarification:
msdn documentation says that instance methods are not thread-safe. However
when i run the spinnet below i do not get any exception not matter how long i
run it for. Any advice on how i should be using the Queue class with calls to
Enqueue and Dequeue would be greatly appreciated

Code Snip:
-----------------------------------------------
using System;
using System.Collections;
using System.Threading;

public class MyClass
{
private static Queue oQueue = null;
private static bool bContinue = true;

public static void Main()
{
oQueue = new Queue();

Thread oThread1 = new Thread(new ThreadStart(WriteQueue));
Thread oThread2 = new Thread(new ThreadStart(ReadQueue));
oThread1.Start();

oThread2.Start();
RL();
}

private static void ReadQueue()
{
while(true)
{
if(oQueue.Count > 0)
{
int nValue = (int)oQueue.Dequeue();
Console.WriteLine("Read from Queue: {0}", nValue);
}
}
}

private static void WriteQueue()
{
for(int i = 1; i < 10000; i++)
{
oQueue.Enqueue(i);
Console.WriteLine("Writing to Queue: {0}", i);
}
bContinue = false;
}

#region Helper methods

private static void WL(object text, params object[] args)
{
Console.WriteLine(text.ToString(), args);
}

private static void RL()
{
Console.ReadLine();
}

private static void Break()
{
System.Diagnostics.Debugger.Break();
}

#endregion
}
 
B

Brian Gideon

Hi,

I am in need to a Queue class for a high speed read write operation where i
do not have to look the object / collection in order to add / remove items. I
had a look at System.Collections.Queue class and i need some clarification:
msdn documentation says that instance methods are not thread-safe. However
when i run the spinnet below i do not get any exception not matter how long i
run it for. Any advice on how i should be using the Queue class with calls to
Enqueue and Dequeue would be greatly appreciated

Code Snip:
-----------------------------------------------
using System;
using System.Collections;
using System.Threading;

public class MyClass
{
private static Queue oQueue = null;
private static bool bContinue = true;

public static void Main()
{
oQueue = new Queue();

Thread oThread1 = new Thread(new ThreadStart(WriteQueue));
Thread oThread2 = new Thread(new ThreadStart(ReadQueue));
oThread1.Start();

oThread2.Start();
RL();
}

private static void ReadQueue()
{
while(true)
{
if(oQueue.Count > 0)
{
int nValue = (int)oQueue.Dequeue();
Console.WriteLine("Read from Queue: {0}", nValue);
}
}
}

private static void WriteQueue()
{
for(int i = 1; i < 10000; i++)
{
oQueue.Enqueue(i);
Console.WriteLine("Writing to Queue: {0}", i);
}
bContinue = false;
}

#region Helper methods

private static void WL(object text, params object[] args)
{
Console.WriteLine(text.ToString(), args);
}

private static void RL()
{
Console.ReadLine();
}

private static void Break()
{
System.Diagnostics.Debugger.Break();
}

#endregion}

If it's working then it's doing so by accident. Also, the absence of
an exception does not mean that the application is devoid of
unintended side effects. You'll have to synchronize access to the
Queue if you wish to read or write from multiple threads.
 
A

Andy

I am in need to a Queue class for a high speed read write operation where i
do not have to look the object / collection in order to add / remove items. I
had a look at System.Collections.Queue class and i need some clarification:
msdn documentation says that instance methods are not thread-safe. However
when i run the spinnet below i do not get any exception not matter how long i
run it for. Any advice on how i should be using the Queue class with calls to
Enqueue and Dequeue would be greatly appreciated

I can't comment on the speed of the class, you'll have to investigate
yourself, but you will likely run into threading issues with the code
you posted. The problem with threading is concurrency issues may not
manifest themselves initially, on serveral machines. For example, are
you on a single processor or multiprocessor / core workstation? If
you're on a single processor / core, you may not notice any issues
until you move to more than one processor. Even on your single core,
you may experience problems eventually, especially if your operation
is long running, because you never know when the thread will be
switched.

If Queue has a SyncRoot, I would recommend locking on that; otherwise,
device your own lock object to lock on. Either way, you really should
be ensuring proper syncronization.
 
S

Steven Cheng[MSFT]

Hi Hermit,

As the MSDN document mentioned, the Queue class's instance methods are not
guaranteed to be thread safe. When you try calling instance
methods/properties against a shared queue instance from multiple threads,
you're recommended to use the wrapper return from "Queue.Synchronized"
method:

====================
Queue queue = new Queue();

//get the synchronized wapper
Queue syncQueue = Queue.Synchronized(queue);

// use syncQueue instead
====================

Also, concurrent access to Queue's instance methods will cause logic
incorrect and inconsistent behavior, but the runtime will not through
exception since they do not cause runtime error. However, if you will
perform enumeration against Queue object, you'd better lock it
first(through the SyncRoot property in each thread) or you can copy the
Queue's items into Array for enumeration:

#Queue.Synchronized Method
http://msdn2.microsoft.com/en-us/library/system.collections.queue.synchroniz
ed.aspx

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.
 
O

oscar.acostamontesde

Hi,

I am in need to a Queue class for a high speed read write operation where i
do not have to look the object / collection in order to add / remove items. I
had a look at System.Collections.Queue class and i need some clarification:
msdn documentation says that instance methods are not thread-safe. However
when i run the spinnet below i do not get any exception not matter how long i
run it for. Any advice on how i should be using the Queue class with calls to
Enqueue and Dequeue would be greatly appreciated

Code Snip:
-----------------------------------------------
using System;
using System.Collections;
using System.Threading;

public class MyClass
{
private static Queue oQueue = null;
private static bool bContinue = true;

public static void Main()
{
oQueue = new Queue();

Thread oThread1 = new Thread(new ThreadStart(WriteQueue));
Thread oThread2 = new Thread(new ThreadStart(ReadQueue));
oThread1.Start();

oThread2.Start();
RL();
}

private static void ReadQueue()
{
while(true)
{
if(oQueue.Count > 0)
{
int nValue = (int)oQueue.Dequeue();
Console.WriteLine("Read from Queue: {0}", nValue);
}
}
}

private static void WriteQueue()
{
for(int i = 1; i < 10000; i++)
{
oQueue.Enqueue(i);
Console.WriteLine("Writing to Queue: {0}", i);
}
bContinue = false;
}

#region Helper methods

private static void WL(object text, params object[] args)
{
Console.WriteLine(text.ToString(), args);
}

private static void RL()
{
Console.ReadLine();
}

private static void Break()
{
System.Diagnostics.Debugger.Break();
}

#endregion}

Hello:
Also you can use a sync object, and place queue acces code in a lock
statement.
object o = new object();
lock(o){
//Queue operations...
}
Best regards.
Oscar Acosta
 
G

Guest

Thank you gentleman. I will have a look at the Queue.Synchronized object.

I was trying to avoid explicit lock statements as i need it for a high speed
operation.
thanks for all your replies.
 
G

Guest

I have modified the code to use a local syncronized wrapper as below. Will
this work without thread concurrency issues in a multi threaded environment ?:

private static Queue oQueue = null;
private static bool bContinue = true;

public static void Main()
{
oQueue = new Queue();

Thread oThread1 = new Thread(new ThreadStart(WriteQueue));
Thread oThread2 = new Thread(new ThreadStart(ReadQueue));
oThread1.Start();
oThread2.Start();
}

private static void ReadQueue()
{
Queue localQueue = Queue.Synchronized(oQueue);
while(true)
{
if(localQueue.Count > 0)
{
int nValue = (int)localQueue.Dequeue();
Console.WriteLine("Read from Queue: {0}", nValue);
}
}
}

private static void WriteQueue()
{
Queue localQueue = Queue.Synchronized(oQueue);

for(int i = 1; i < 100; i++)
{
localQueue.Enqueue(i);
Console.WriteLine("Writing to Queue: {0}", i);
}
bContinue = false;
}
 
G

Guest

I forgot to add that i do not wish to enumerate using foreach or using
IEnumerator

I would like to use Enqueue and Dequeue functions. Does the use of
Queue.Syncronized wrapper make them threadsafe ? or would i be better of
using
lock( myCollection.SyncRoot ) before calling Enqueue or Dequeue methods on
the syncronised wrapper ?

--
Regards,

Hermit Dave
http://www.invokeit.co.uk
 
R

Rory Becker

I have modified the code to use a local syncronized wrapper as below.
Will this work without thread concurrency issues in a multi threaded
environment ?:


I would like to tak an extra question on to this one.

I am interested in using a HashTable in a similar fashion.

I was wondering is the "local sychronized wrapper" technique applicable here?

Likewise will using this synchronised object ensure that I am thread safe
with regard to my HashTable/Queue?

Thanks in advance
 
J

Jon Skeet [C# MVP]

Hermit Dave said:
Thank you gentleman. I will have a look at the Queue.Synchronized object.

I was trying to avoid explicit lock statements as i need it for a high speed
operation.

Have you measured the overhead of locking? I think you'll find it's
pretty cheap when there isn't contention.
 
S

Steven Cheng[MSFT]

Thanks for your reply Hermit,

Here is the remark of the Queue class thread safety picked from my local
MSDN:

/***** MSDN remark on Queue class's thread safety*****/

Public static (Shared in Visual Basic) members of this type are thread
safe. Any instance members are not guaranteed to be thread safe.

To guarantee the thread safety of the Queue, 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 can 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.

/****************************************************************/

As it mentioned, for normal enqueue/dequeue processing, the returned
wrapper through "Synchronized" method should has taken care of the thread
safety. It is only when you need to enumerate the queue items will you need
to lock it.

Sincerely,

Steven Cheng

Microsoft MSDN Online Support Lead


This posting is provided "AS IS" with no warranties, and confers no rights.
 
W

William Stacey [C# MVP]

In that case, you would be double-locking. If using sync wrapper, the calls
to Enqueue and Dequeue are safe. If you enum, you need to
lock(q.SyncRoot){foreach...}

--
William Stacey [C# MVP]


|I forgot to add that i do not wish to enumerate using foreach or using
| IEnumerator
|
| I would like to use Enqueue and Dequeue functions. Does the use of
| Queue.Syncronized wrapper make them threadsafe ? or would i be better of
| using
| lock( myCollection.SyncRoot ) before calling Enqueue or Dequeue methods on
| the syncronised wrapper ?
|
| --
| Regards,
|
| Hermit Dave
| http://www.invokeit.co.uk
|
|
| "Hermit Dave" wrote:
|
| > I have modified the code to use a local syncronized wrapper as below.
Will
| > this work without thread concurrency issues in a multi threaded
environment ?:
| >
| > private static Queue oQueue = null;
| > private static bool bContinue = true;
| >
| > public static void Main()
| > {
| > oQueue = new Queue();
| >
| > Thread oThread1 = new Thread(new ThreadStart(WriteQueue));
| > Thread oThread2 = new Thread(new ThreadStart(ReadQueue));
| > oThread1.Start();
| > oThread2.Start();
| > }
| >
| > private static void ReadQueue()
| > {
| > Queue localQueue = Queue.Synchronized(oQueue);
| > while(true)
| > {
| > if(localQueue.Count > 0)
| > {
| > int nValue = (int)localQueue.Dequeue();
| > Console.WriteLine("Read from Queue: {0}", nValue);
| > }
| > }
| > }
| >
| > private static void WriteQueue()
| > {
| > Queue localQueue = Queue.Synchronized(oQueue);
| >
| > for(int i = 1; i < 100; i++)
| > {
| > localQueue.Enqueue(i);
| > Console.WriteLine("Writing to Queue: {0}", i);
| > }
| > bContinue = false;
| > }
| > --
| > Regards,
| >
| > Hermit Dave
| > http://www.invokeit.co.uk
| >
| >
| > "Steven Cheng[MSFT]" wrote:
| >
| > > Hi Hermit,
| > >
| > > As the MSDN document mentioned, the Queue class's instance methods are
not
| > > guaranteed to be thread safe. When you try calling instance
| > > methods/properties against a shared queue instance from multiple
threads,
| > > you're recommended to use the wrapper return from "Queue.Synchronized"
| > > method:
| > >
| > > ====================
| > > Queue queue = new Queue();
| > >
| > > //get the synchronized wapper
| > > Queue syncQueue = Queue.Synchronized(queue);
| > >
| > > // use syncQueue instead
| > > ====================
| > >
| > > Also, concurrent access to Queue's instance methods will cause logic
| > > incorrect and inconsistent behavior, but the runtime will not through
| > > exception since they do not cause runtime error. However, if you will
| > > perform enumeration against Queue object, you'd better lock it
| > > first(through the SyncRoot property in each thread) or you can copy
the
| > > Queue's items into Array for enumeration:
| > >
| > > #Queue.Synchronized Method
| > >
http://msdn2.microsoft.com/en-us/library/system.collections.queue.synchroniz
| > > ed.aspx
| > >
| > > Sincerely,
| > >
| > > Steven Cheng
| > >
| > > Microsoft MSDN Online Support Lead
| > >
| > >
| > > This posting is provided "AS IS" with no warranties, and confers no
rights.
| > >
| > >
| > >
| > >
| > >
 
O

oscar.acostamontesde

Just to clarify...the object used in the lock statement must be the
same in every thread to guarentee thread-safety. It's difficult to
ascertain what your intention from the code was precisely, but one way
to read it is that the variable o is local and thus would be different
on every thread.

Yes, you're rigth, code is not clear. Object o should be a class
memeber, with class scope, so it is always locking on same object.
public class Queue{
private static readonly object o = new object();

private void ReadQueue(){
lock(o){
int nValue = (int)localQueue.Dequeue();
Console.WriteLine("Read from Queue: {0}", nValue);
}
}
}

Best regards
Oscar Acosta
 
G

Guest

Thanks William.

--
Regards,

Hermit Dave
http://www.invokeit.co.uk


William Stacey said:
In that case, you would be double-locking. If using sync wrapper, the calls
to Enqueue and Dequeue are safe. If you enum, you need to
lock(q.SyncRoot){foreach...}

--
William Stacey [C# MVP]


|I forgot to add that i do not wish to enumerate using foreach or using
| IEnumerator
|
| I would like to use Enqueue and Dequeue functions. Does the use of
| Queue.Syncronized wrapper make them threadsafe ? or would i be better of
| using
| lock( myCollection.SyncRoot ) before calling Enqueue or Dequeue methods on
| the syncronised wrapper ?
|
| --
| Regards,
|
| Hermit Dave
| http://www.invokeit.co.uk
|
|
| "Hermit Dave" wrote:
|
| > I have modified the code to use a local syncronized wrapper as below.
Will
| > this work without thread concurrency issues in a multi threaded
environment ?:
| >
| > private static Queue oQueue = null;
| > private static bool bContinue = true;
| >
| > public static void Main()
| > {
| > oQueue = new Queue();
| >
| > Thread oThread1 = new Thread(new ThreadStart(WriteQueue));
| > Thread oThread2 = new Thread(new ThreadStart(ReadQueue));
| > oThread1.Start();
| > oThread2.Start();
| > }
| >
| > private static void ReadQueue()
| > {
| > Queue localQueue = Queue.Synchronized(oQueue);
| > while(true)
| > {
| > if(localQueue.Count > 0)
| > {
| > int nValue = (int)localQueue.Dequeue();
| > Console.WriteLine("Read from Queue: {0}", nValue);
| > }
| > }
| > }
| >
| > private static void WriteQueue()
| > {
| > Queue localQueue = Queue.Synchronized(oQueue);
| >
| > for(int i = 1; i < 100; i++)
| > {
| > localQueue.Enqueue(i);
| > Console.WriteLine("Writing to Queue: {0}", i);
| > }
| > bContinue = false;
| > }
| > --
| > Regards,
| >
| > Hermit Dave
| > http://www.invokeit.co.uk
| >
| >
| > "Steven Cheng[MSFT]" wrote:
| >
| > > Hi Hermit,
| > >
| > > As the MSDN document mentioned, the Queue class's instance methods are
not
| > > guaranteed to be thread safe. When you try calling instance
| > > methods/properties against a shared queue instance from multiple
threads,
| > > you're recommended to use the wrapper return from "Queue.Synchronized"
| > > method:
| > >
| > > ====================
| > > Queue queue = new Queue();
| > >
| > > //get the synchronized wapper
| > > Queue syncQueue = Queue.Synchronized(queue);
| > >
| > > // use syncQueue instead
| > > ====================
| > >
| > > Also, concurrent access to Queue's instance methods will cause logic
| > > incorrect and inconsistent behavior, but the runtime will not through
| > > exception since they do not cause runtime error. However, if you will
| > > perform enumeration against Queue object, you'd better lock it
| > > first(through the SyncRoot property in each thread) or you can copy
the
| > > Queue's items into Array for enumeration:
| > >
| > > #Queue.Synchronized Method
| > >
http://msdn2.microsoft.com/en-us/library/system.collections.queue.synchroniz
| > > ed.aspx
| > >
| > > Sincerely,
| > >
| > > Steven Cheng
| > >
| > > Microsoft MSDN Online Support Lead
| > >
| > >
| > > This posting is provided "AS IS" with no warranties, and confers no
rights.
| > >
| > >
| > >
| > >
| > >
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top