return RoleStatus.Healthy; } } } Create the Queue Programatically Listing 3-3 is an example of creating a queue programatically inside a C# class instead of reading the information fr
Trang 173
bool containerAndQueueCreated = false;
while (!containerAndQueueCreated)
{
try
{
queue.CreateQueue();
containerAndQueueCreated = true;
}
catch (WebException e)
{
if (e.Status == WebExceptionStatus.ConnectFailure)
{
RoleManager.WriteToLog(
"Error",
string.Format("Connect failure! The most likely reason is that
the local Development Storage tool is not running or your storage account configuration is
incorrect " +
"Message: '{0}'", e.Message)
);
System.Threading.Thread.Sleep(5000);
}
else
{
throw;
}
}
}
while (true)
{
try
{
Message msg = queue.GetMessage();
if (msg != null)
{
string path = msg.ContentAsString();
RoleManager.WriteToLog("Information",
string.Format("Done with '{0}'", path));
}
else
{
Thread.Sleep(1000);
}
}
catch (StorageException e)
{
RoleManager.WriteToLog(
"Error",
string.Format("Exception when processing queue item Message: '{0}'", e.Message)
Trang 274
);
}
}
}
public override RoleStatus GetHealthStatus()
{
// This is a sample worker implementation Replace with your logic
return RoleStatus.Healthy;
}
}
}
Create the Queue Programatically
Listing 3-3 is an example of creating a queue programatically inside a C# class instead of reading the information from a configuration file This code snippet can be used to replace the highlighted part in Listing 3-2
Listing 3-3 Create the Queue Programatically
string accountName = "devstoreaccount1";
string accountKey = "<ACCOUNT KEY>";
string address = "http://127.0.0.1:10001";
StorageAccountInfo accountInfo =
new StorageAccountInfo(new Uri(address), null, accountName, accountKey);
QueueStorage queueStorage = QueueStorage.Create(accountInfo);
MessageQueue messageQueue = queueStorage.GetQueue(XML PAYLOAD QUEUE NAME);
Before a client can access the cloud queue one of the two initialization steps shown in the previous listing is required
Put a Message into the Queue
There are three data types you can use as a raw queue message: stream, byte array, and string
In this exercise we are going to use the class Address defined in Chapter 1 and Chapter 2 as a data entity class Since XML is the most popular data exchange format, we are going to transform the data of
an instance of Address into an XML string by using the NET XmlSerialization class and put it into the queue as a message Listing 3-4 shows the code to transform the data entity Address into an XML string and put it into the queue as a queue message
Trang 375
Unlike the behavior of a regular Windows queue object, when a message is put into the cloud queue
it can be read (de-queued) multiple times by applications The message will not be removed from the
queue until another service calls to delete the queue explicitly The message body is encoded and stored
in a data field of the Message table after the message has been put into the queue Figure 3-5 shows the
data query results from the local database when the message is submitted to the queue in the local
development environment The data has been encoded as you can see
Listing 3-4 Convert Address Data Entity Object into XML String and Put into Queue
protected void btnAddAddress Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
GetXmlPayloadQueue().PutMessage(new Message( ComposeXmlString()));
}
}
private string ComposeXmlString()
{
Address address = new Address(txtAddress1.Text.Trim(),
txtAddress2.Text.Trim(),
txtCity.Text.Trim(),
(State)combState.SelectedIndex,
txtZip.Text.Trim(),
txtCounty.Text.Trim(),
txtCountry.Text.Trim(),
string.Empty);
XmlSerializer serializer = new XmlSerializer(address.GetType());
StringBuilder sb = new StringBuilder();
StringWriter writer = new StringWriter(sb);
serializer.Serialize(writer, address);
return writer.GetStringBuilder().ToString();
}
private BlobContainer GetXmlPayloadContainer()
{
Initialization();
return blobStorage.GetBlobContainer(WorkerRole.XML CONTAINER NAME);
}
private MessageQueue GetXmlPayloadQueue()
{
Initialization();
return queueStorage.GetQueue(WorkerRole.XML PAYLOAD QUEUE NAME);
}
Trang 476
protected void btnDelete Click(object sender, EventArgs e)
{
Message message = GetXmlPayloadQueue().GetMessage(UPDATE TIMEOUT SEC);
if (message != null)
{
GetXmlPayloadQueue().DeleteMessage(message);
}
}
Figure 3-5 Queue message persisted in data field of Message table and encoded
Poll and Delete a Message from the Queue
The MessageQueue class defined in the StorageClient assembly also provides polling infrastructure under the covers and delivers the message via venting The default poll interval setting in the
MessageQueue class is 30 seconds This polling interval value can be set during initialization of a queue instance Listing 3-5 is the initialization handler implemented in the code behind Default.aspx.cs
To receive the queue polling events, a local event-handler function needs to be defined The event handler function is called private void OnMessageReceive(object sender, EventArgs args), which has the typical event-handler signature with two parameters The first parameter is the basic object type, and the second parameter is the EventArgs type The application can have any logic it needs in the event-polling handler In this example, we simply print out the content of the message polled from the queue As the highlighted part shows in Listing 3-5, the event handler is hooked up right after the queue is created This function also uses the synchronization object syncObj to make it thread-safe in
a multi-thread environment
Trang 577
■ Note Never call queue.StartReceiving() if there is no event handler such as queue.MessageReceived += new MessageReceivedEventHandler( OnMessageReceive) implemented in the class Otherwise it causes a
NullObject reference exception to be thrown at runtime
Listing 3-5 Polling the Queue and Handling Received Events
private void Initialization()
{
if ( initialized)
{
return;
}
lock ( syncObj)
{
try
{
queueStorage =
QueueStorage.Create(StorageAccountInfo
GetDefaultQueueStorageAccountFromConfiguration());
MessageQueue queue =
queueStorage.GetQueue(WorkerRole.XML PAYLOAD QUEUE NAME);
queue.MessageReceived +=
new MessageReceivedEventHandler(_OnMessageReceive);
queue.PollInterval = 1000; // in milliseconds
queue.StartReceiving(); // start polling
}
catch (WebException ex)
{
throw new WebException(
string.Format(
" -{0}: Initialization, Azure failed to instatiate storage using
current account information exception caught : {1}",
this.ToString(),
ex.Message
)
);
}
initialized = true;
}
}
private void OnMessageReceive(object sender, EventArgs args)
{
Message message = (args as MessageReceivedEventArgs).Message;