Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Problem with Logic / Textbook 1

Status
Not open for further replies.

Triacona

Technical User
Jun 11, 2009
462
GB
Hi all,
This is a bit of a weird one.
I came across an example in my textbook and tried it out.
It is to do with:
Using the ConcurrentQueue<T> Collection
Here is the textbook example as provided ( DID NOT WORK )
Code:
class Program 
{ 
   static ConcurrentQueue<string> queue = new ConcurrentQueue<string>();   
   
   static void PlaceOrders() 
   { 
      for (int i = 1; i <= 100; i++) 
      { 
         Thread.Sleep(250); 
         String order = String.Format("Order {0}", i);          
         queue.Enqueue(order); 
         Console.WriteLine("Added {0}", order); 
      }    
   } 
   static void ProcessOrders() 
   { 
      	while (true) //continue indefinitely       
	if (queue.TryDequeue(out order)) 
      	{ 
                  Console.WriteLine("Processed {0}", order); 
      	}    
   }    
   static void Main(string[] args) 
   { 
      	var taskPlaceOrders = Task.Run(() => PlaceOrders()); 
      	Task.Run(() => ProcessOrders()); 
      	Task.Run(() => ProcessOrders());       
      	Task.Run(() => ProcessOrders());       
	taskPlaceOrders.Wait(); 
      	Console.WriteLine("Press ENTER to finish"); 
      	Console.ReadLine(); 
   } 
}
Then I went and "fixed" it...
Code:
 static ConcurrentQueue<string> queue = new ConcurrentQueue<string>();
        private static string order;
       
        static void PlaceOrders()
        {
            
            for (int i = 1; i <= 100; i++)
            {
               
                Thread.Sleep(1000);
                String order = String.Format("Order {0}", i);
                queue.Enqueue(order);
                Console.WriteLine("Added {0}", order);
                
                

            }
        }

        static void ProcessOrders()
        {
            while (true) // continue indefinitely
            
                if (queue.TryDequeue(out order))
                {
                    Console.WriteLine("Processed {0}", order);   
                }
            
        }
As you can see order is declared twice, and no error, and gave good output...
If I removed the String from in front of order ( the variable declared within the For loop ) it stopped working, it compiled, but the output was not working as desired.Below...
Code:
class Program
    {
        #region Lesson 3
        #region Using the ConcurrentQueue<T> Collection

        static ConcurrentQueue<string> queue = new ConcurrentQueue<string>();
        private static string order;
       
        static void PlaceOrders()
        {
            
            for (int i = 1; i <= 100; i++)
            {
               
                Thread.Sleep(1000);
                 order = String.Format("Order {0}", i);
                queue.Enqueue(order);
                Console.WriteLine("Added {0}", order);
                
                

            }
        }

        static void ProcessOrders()
        {
            while (true) // continue indefinitely
            
                if (queue.TryDequeue(out order))
                {
                    Console.WriteLine("Processed {0}", order);   
                }
            
        }
There are some questions I would like to raise from the above:
1. I understand that the field order was required, but why is it necessary to declare it again as a String object in the for loop?
2. Why does the Add order ... not work if I remove the String keyword?
3. In the queue.TryDequeue( out order ) ), tryDequeue is accepting a parameter to test true or false right?

Thank you for the forthcoming answers [smile]
And thank you all for a great forum! [thumbsup]


Thank you,

Kind regards

Triacona
 
Hi Triacona,

I must admit I do not quite understand your problem. Have you "fixed" something else that is not mentioned here?
This here works just fine for me:
Code:
class Program
{
	static ConcurrentQueue<string> queue = new ConcurrentQueue<string>();

	private static string order;

	static void PlaceOrders()
	{
		for (int i = 1; i <= 20; i++)
		{
			Thread.Sleep(250);
			order = String.Format("Order {0}", i);
			queue.Enqueue(order);
			Console.WriteLine("Added {0}", order);
		}
	}
	static void ProcessOrders()
	{
		while (true) //continue indefinitely       
			if (queue.TryDequeue(out order))
			{
				Console.WriteLine("Processed {0}", order);
			}
	}
	static void Main(string[] args)
	{
		var taskPlaceOrders = Task.Run(() => PlaceOrders());
		Task.Run(() => ProcessOrders());
		Task.Run(() => ProcessOrders());
		Task.Run(() => ProcessOrders());
		taskPlaceOrders.Wait();
		Console.WriteLine("Press ENTER to finish");
		Console.ReadLine();
	}
}

Best,
MakeItSo

"Knowledge is power. Information is liberating. Education is the premise of progress, in every society, in every family." (Kofi Annan)
Oppose SOPA, PIPA, ACTA; measures to curb freedom of information under whatever name whatsoever.
 
Thank you for you reply [Thumbsup]
But when you run your version the output is incorrect see below:
Added
Processed
Added
Processed Order 7
Added
Processed
Added
Processed
Added Order 10
Processed Order 10
Added Order 11
Processed Order 11

each line should have a number...
Thanks.

Thank you,

Kind regards

Triacona
 
Indeed! [3eyes]
I will try to find out. Must have something to do with TryDequeue and what exactly it returns as well as with having a global variable. There can always be unexpected side-effects.
It's a weird one though.

"Knowledge is power. Information is liberating. Education is the premise of progress, in every society, in every family." (Kofi Annan)
Oppose SOPA, PIPA, ACTA; measures to curb freedom of information under whatever name whatsoever.
 
Got it!
It was indeed a side-effect of the global string variable. This here works just fine (really now), note the two bolded lines:
Code:
class Program
{
	static ConcurrentQueue<string> queue = new ConcurrentQueue<string>();

	static void PlaceOrders()
	{
		[b]string order;[/b]
		for (int i = 1; i <= 20; i++)
		{
			order = $"Order {i}";
			queue.Enqueue(order);
			Thread.Sleep(100);
			Console.WriteLine("Added {0}", order);
		}
	}
	static void ProcessOrders()
	{
		[b]string test;[/b]
		while (true) //continue indefinitely       
			if (queue.TryDequeue(out test))
			{
				Console.WriteLine("Processed {0}", test);
			}
	}

	static void Main(string[] args)
	{
		var taskPlaceOrders = Task.Run(() => PlaceOrders());
		Task.Run(() => ProcessOrders());
		Task.Run(() => ProcessOrders());
		Task.Run(() => ProcessOrders());
		taskPlaceOrders.Wait();
		Console.WriteLine("Press ENTER to finish");
		Console.ReadLine();
	}
}

"Knowledge is power. Information is liberating. Education is the premise of progress, in every society, in every family." (Kofi Annan)
Oppose SOPA, PIPA, ACTA; measures to curb freedom of information under whatever name whatsoever.
 
Thanks so very much!
This is an odd one.
So let me try get this straight in my head...

1. order is declared a string in the PlaceOrders() method.
2. order is assigned Order {i} and that is then added to the queue.
3. in the method ProcessOrders, another string is declared as order ( or your case test ).
4. queue is called using the queue.TryDequeue method which requires an out parameter.
5. the queue.TryDequeue method de-queues the queue object in the same order as added ( in first out first ).
6. the value is assigned to order ( or test ) using the out keyword?
7. .'. so in conclusion the method does 2 things, returns a bool and assigns the de-queued item to the variable given?

Thanks again for your help [bigsmile]


Thank you,

Kind regards

Triacona
 
Yes sort of. Only for point 3 it is different:
the string "test" is not declared as "order". Rather, "order" is already fixed into the queue, the "out ..." variable is simply a container that receives the returned value (of order).
So basically string test becomes a local copy of order.
By using a global variable you kept overwriting the value everytime you accessed the queue whileit was still running.
:)

"Knowledge is power. Information is liberating. Education is the premise of progress, in every society, in every family." (Kofi Annan)
Oppose SOPA, PIPA, ACTA; measures to curb freedom of information under whatever name whatsoever.
 
Thanks so much, much appreciated.
[thumbsup]

Thank you,

Kind regards

Triacona
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top