In this post you will create a worker role to read work items posted to a queue by the web role front-end. The worker role performs these tasks:
Figure 7 Creating Worker Role Project
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; using Microsoft.WindowsAzure.Diagnostics; using Microsoft.WindowsAzure.ServiceRuntime; using System.Drawing; using System.IO; using GuestBook_Data; using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.StorageClient; namespace GuestBook_WorkerRole { public class WorkerRole : RoleEntryPoint { private CloudQueue queue; private CloudBlobContainer container; public override void Run() { Trace.TraceInformation("Listening for queue messages..."); while (true) { try { // retrieve a new message from the queue CloudQueueMessage msg = queue.GetMessage(); if (msg != null) { // parse message retrieved from queue var messageParts = msg.AsString.Split(new char[] { ',' }); var uri = messageParts[0]; var partitionKey = messageParts[1]; var rowkey = messageParts[2]; Trace.TraceInformation("Processing image in blob '{0}'.", uri); // download original image from blob storage CloudBlockBlob imageBlob = container.GetBlockBlobReference(uri); MemoryStream image = new MemoryStream(); imageBlob.DownloadToStream(image); image.Seek(0, SeekOrigin.Begin); // create a thumbnail image and upload into a blob string thumbnailUri = String.Concat(Path.GetFileNameWithoutExtension(uri), "_thumb.jpg"); CloudBlockBlob thumbnailBlob = container.GetBlockBlobReference(thumbnailUri); thumbnailBlob.UploadFromStream(CreateThumbnail(image)); // update the entry in table storage to point to the thumbnail var ds = new GuestBookEntryDataSource(); ds.UpdateImageThumbnail(partitionKey, rowkey, thumbnailBlob.Uri.AbsoluteUri); // remove message from queue queue.DeleteMessage(msg); Trace.TraceInformation("Generated thumbnail in blob '{0}'.", thumbnailBlob.Uri); } else { System.Threading.Thread.Sleep(1000); } } catch (StorageClientException e) { Trace.TraceError("Exception when processing queue item. Message: '{0}'", e.Message); System.Threading.Thread.Sleep(5000); } } } public override bool OnStart() { DiagnosticMonitor.Start("DiagnosticsConnectionString"); // Restart the role upon all configuration changes RoleEnvironment.Changing += RoleEnvironmentChanging; // Set the global configuration setting publisher for the storage account, which // will be called when the account access keys are updated in the service configuration file. // Calling SetConfigurationSettingPublisher in OnStart method is important otherwise the // system raises an exception when FromConfigurationSetting is called. CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) => { try { configSetter(RoleEnvironment.GetConfigurationSettingValue(configName)); } catch (RoleEnvironmentException e) { Trace.TraceError(e.Message); System.Threading.Thread.Sleep(5000); } }); // Create a new instance of a CloudStorageAccount object from a specified configuration setting. // This method may be called only after the SetConfigurationSettingPublisher // method has been called to configure the global configuration setting publisher. // You can call the SetConfigurationSettingPublisher method in the OnStart method // of the worker role before calling FromConfigurationSetting. // If you do not do this, the system raises an exception. var storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString"); // initialize blob storage CloudBlobClient blobStorage = storageAccount.CreateCloudBlobClient(); container = blobStorage.GetContainerReference("guestbookpics"); // initialize queue storage CloudQueueClient queueStorage = storageAccount.CreateCloudQueueClient(); queue = queueStorage.GetQueueReference("guestthumbs"); Trace.TraceInformation("Creating container and queue..."); bool storageInitialized = false; while (!storageInitialized) { try { // create the blob container and allow public access container.CreateIfNotExist(); // container.CreateIfNotExist(); var permissions = container.GetPermissions(); permissions.PublicAccess = BlobContainerPublicAccessType.Container; container.SetPermissions(permissions); // create the message queue queue.CreateIfNotExist(); storageInitialized = true; } catch (StorageClientException e) { if (e.ErrorCode == StorageErrorCode.TransportError) { Trace.TraceError("Storage services initialization failure. " + "Check your storage account configuration settings. If running locally, " + "ensure that the Development Storage service is running. Message: '{0}'", e.Message); System.Threading.Thread.Sleep(5000); } else { throw; } } } return base.OnStart(); } private void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e) { if (e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange)) e.Cancel = true; } private Stream CreateThumbnail(Stream input) { var orig = new Bitmap(input); int width; int height; if (orig.Width > orig.Height) { width = 128; height = 128 * orig.Height / orig.Width; } else { height = 128; width = 128 * orig.Width / orig.Height; } var thumb = new Bitmap(width, height); using (Graphics graphic = Graphics.FromImage(thumb)) { graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; graphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; graphic.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; graphic.DrawImage(orig, 0, 0, width, height); var ms = new MemoryStream(); thumb.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); ms.Seek(0, SeekOrigin.Begin); return ms; } } } }
In order for the worker role to use Windows Azure storage services, you must provide account settings as described next.
Figure 8 Configuring Storage Account For Worker Role
For related topics, see the following posts.
All the code is truncated on the right side.