|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
framework 1.1 & Queue classI 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 } ----------------------------------------------- On Apr 23, 11:02 am, Hermit Dave <herm...@newsgroup.nospam> wrote:
Show quote > Hi, If it's working then it's doing so by accident. Also, the absence of> > 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} > > ----------------------------------------------- > > -- > Regards, > > Hermit Davehttp://www.invokeit.co.uk 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. On Apr 23, 12:02 pm, Hermit Dave <herm...@newsgroup.nospam> wrote:
> I am in need to a Queue class for a high speed read write operation where i I can't comment on the speed of the class, you'll have to investigate> 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 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. 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. 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. Show quote "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. > > > > > Hermit Dave <hermitd@newsgroup.nospam> wrote:
> Thank you gentleman. I will have a look at the Queue.Synchronized object. Have you measured the overhead of locking? I think you'll find it's > > I was trying to avoid explicit lock statements as i need it for a high speed > operation. pretty cheap when there isn't contention. -- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too 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; } Show quote "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. > > > > > 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 ? Show quote "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. > > > > > > > > > > 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. Thanks Steven,
I will keep that in mind. Show quote "Steven Cheng[MSFT]" wrote: > 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. > > > > 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...} -- Show quoteWilliam Stacey [C# MVP] "Hermit Dave" <hermitd@newsgroup.nospam> wrote in message http://msdn2.microsoft.com/en-us/library/system.collections.queue.synchroniznews:E1702A63-C5A1-485D-8C63-075179A37B19@microsoft.com... |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 | > > Show quote | > > ed.aspx | > > | > > Sincerely, | > > | > > Steven Cheng | > > | > > Microsoft MSDN Online Support Lead | > > | > > | > > This posting is provided "AS IS" with no warranties, and confers no rights. | > > | > > | > > | > > | > > Thanks William.
Show quote "William Stacey [C# MVP]" wrote: > 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] > > > "Hermit Dave" <hermitd@newsgroup.nospam> wrote in message > news:E1702A63-C5A1-485D-8C63-075179A37B19@microsoft.com... > |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. > | > > > | > > > | > > > | > > > | > > > > > > I have modified the code to use a local syncronized wrapper as below. I would like to tak an extra question on to this one.> Will this work without thread concurrency issues in a multi threaded > environment ?: 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 -- Rory On Apr 23, 6:02 pm, Hermit Dave <herm...@newsgroup.nospam> wrote:
Show quote > Hi, Hello:> > 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} > > ----------------------------------------------- > > -- > Regards, > > Hermit Davehttp://www.invokeit.co.uk 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 |
|||||||||||||||||||||||