Transact SQL Other Articles Software Reviews
Using the Queue Class in the Microsoft .NET Framework
We English people love to queue! So I was especially pleased when Microsoft included the Queue class within the .NET Framework. It's just the thing for creating applications where items must be processed in an orderly fashion.
The Queue class has no equivalent in classic ASP. So it offers the possibility of building functionality that would not have been possible to create before the .NET Framework was released.
The Queue class is a Collection in which items are added to the end of the collection, and are removed from the start of the collection, much like a line for the store checkout. This is often described as a first in, first out (FIFO) type of behaviour. Such a collection is useful if there is a bottleneck in an application (such as sending out emails or validating credit card orders) and you would like the items in the collection processed in a first come, first served basis.
Of particular value to ASP.NET developers is the ability to store Queue collections within Application or Session variables. This allows pages to be created that process a certain number of items in the queue, and then store the rest of the items for processing by a subsequent call to the processing page. I have used this technique in the past to write an ASP.NET page to send out a newsletter email to a large number of subscribers. The bottleneck in the process was that the server component used to send the emails could only handle a maximum number of emails with each call to the page, and the outgoing mail server could only send a certain number of emails per second. So the processing was split into chunks, and the subscriber email addresses stored in a Queue within the Application object between calls to the page. This prevented ASP.NET page timeouts and it also allowed the emails to be sent in batches, preventing excessive load on the mail server.
More recently I've used the Queue class in conjunction with the DynamicPDF PDF generator component for .NET. I used the Queue object to store a collection of custom Customer objects, which were then formatted into individual tables for each customer and output as PDF. Using the Queue object meant that I only needed to iterate the list of customers once, and the customer retrieval code could also be kept separate from the PDF generation code.
Note that the Queue class should not be confused with Microsoft Message Queuing, which is a completely different and unrelated technology!
Using the Queue class
Creating an instance of a Queue class
To create an instance of a queue class, the New keyword can be used. There are two main constructors of note. The first constructor of the class is without any arguments, i.e.
Dim MyQueue As New Queue
The second constructor specifies an integer as the initial size of the queue. The following example creates a queue which can be used to hold twelve objects:
Dim MyQueue As New Queue(12)
Since the queue class automatically grows beyond the specified capacity if more objects are added than the initial size would allow for, it is not usually necessary to specify the size of the queue. However, doing so, especially if you know the queue will be especially large or fixed in length, can improve performance slightly.
When you are intending to use the Queue class, it is sometimes necessary to import the Systems.Collections namespace by using the Imports System.Collections statement in VB.NET or by the using System.Collections; statement in C#.
Adding objects to a Queue
To add an object to a queue, the Enqueue method is used. There is only version of this method, with a single argument: the object to be added to the Queue. Any object can be added to an instance of the Queue class - from basic objects such as integers and strings to other classes and even other Queue classes. It is also possible to add null values using the VB.NET Nothing keyword or the System.DBNull.Value class (or simply null in C#). Each Queue can contain many different types of objects. The code below shows a variety of objects added to an instance of a Queue class:
Dim MyQueue As New Queue(4) Dim MyOtherQueue As New Queue Dim MyNumber As Integer = 12 Dim MyText As String = "This is some text" MyQueue.Enqueue(MyNumber) MyQueue.Enqueue(MyText) MyQueue.Enqueue(MyOtherQueue) MyQueue.Enqueue(System.DBNull.Value)
Again, if adding the object to the queue causes the size of the queue to exceed the current size of the queue, then the queue is automatically resized to allow the object to be added to the queue.
Note that if your Queue will only hold a particular type, you should use the strongly typed Generic Queue: System.Collections.Generic.Queue<T> if you are using .NET 2.0.
Examining the Queue and removing objects from a Queue
An object may be removed from the queue by invoking the Dequeue() method.
Dim DequeuedObject As Object DequeuedObject = MyQueue.Dequeue()
There may be occasions when you would like to examine an object before it is removed from a queue. This is possible by making use of the Peek() method. This method is identical to Dequeue, but it does not actually remove that object from the queue:
Dim DequeuedObject As Object DequeuedObject = MyQueue.Peek()
To determine the number of items in the queue, the Count property always contains an integer value for the number of items in the queue.
The queue can be resized by invoking the TrimToSize() method. This method is helpful for applications in which it is useful to minimise memory usage, as resizing the queue to its current capacity reduces the amount of memory allocated to the queue object.
There is also a Clear() method, which as its name suggests, can be used to completely empty the queue class.
To find if an object is in a queue, the Contains() method can be used. The object to be searched for is used as the method's argument. Since the method invokes the Object.Equals method, it cannot be used if the objects are not exactly the same. This means that in the case of String objects, the search is case sensitive. The following example illustrates this:
Dim MyQueue As New Queue() Dim MyText As String = "ASPAlliance" MyQueue.Enqueue(MyText) If MyQueue.Contains("aspalliance") Then Response.Write("found aspalliance") Else Response.Write("didn't find aspalliance") End If
The string "aspalliance" will not be found in this Queue class due to the case sensitive search used by the Contains() method.
Iterating through the objects in the Queue
It is possible to loop through the items in the queue by using the queue's GetEnumerator method. Although an iterator cannot be used to modify the items in the queue, it allows more sophisticated searching of the queue than is possible using the Contains() method.
While iterating the queue, the Current property can be used to find out about the current item being iterated. The code sample below shows how to loop through the items in a queue using the queue's GetEnumerator method:
'Create an enumerator for a queueand loops through 'the(objects) in the queue. Showsthe type of each object 'in the queue and its stringrepresentation Dim QueueEnumerator As IEnumerator= MyQueue.GetEnumerator() While QueueEnumerator.MoveNext Dim ObjectType As System.Type ObjectType = QueueEnumerator.Current.GetType Response.Write("object name =" & ObjectType.Name) Response.Write(" string representation =" & _ QueueEnumerator.Current.ToString & "") End While
Other useful Queue methods
The Clone() method can be used to create a copy of a queue:
Dim MyOtherQueue As Queue() MyOtherQueue = MyQueue.Clone()
There are also two methods for converting a Queue to an array. The ToArray() method creates a new array from a Queue. The CopyTo() method copies the Queue to an existing array. The CopyTo method takes two arguments: the array to which the Queue needs to be copied, and the starting position of the Queue's contents within the existing array.
To summarise, the Queue collection is one of the many benefits ASP.NET offers over ASP. The Queue collection is well worth considering if you are building any type of system that has to process items with a resource that has limited availability.