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
technology - see http://aspalliance.com/486
for more on Microsoft Message Queuing.
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.
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"
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"
If MyQueue.Contains("aspalliance") Then
Response.Write("didn't find aspalliance")
The string "aspalliance" will not
be found in this Queue class due to the case sensitive search used by the
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()
Dim ObjectType As System.Type
ObjectType = QueueEnumerator.Current.GetType
Response.Write("object name =" & ObjectType.Name)
Response.Write(" string representation =" & _
QueueEnumerator.Current.ToString & "")
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.