In my previous post, I implemented a simple worker role, consuming and producing numbers from/to a queue. Now, I have a new app:
The worker role implements the generation of a Collatz sequence. See:
http://mathworld.wolfram.com/CollatzProblem.html
http://en.wikipedia.org/wiki/Collatz_conjecture
http://www.ericr.nl/wondrous/
You can download the solution from my AjCodeKatas Google project. The code is at:
http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/Azure/AzureCollatz
The initial page is simple:
The number range is send to the queue:
protected void btnProcess_Click(object sender, EventArgs e)
{
int from = Convert.ToInt32(txtFromNumber.Text);
int to = Convert.ToInt32(txtToNumber.Text);
for (int k=from; k<=to; k++)
{
CloudQueueMessage msg = new CloudQueueMessage(k.ToString());
WebRole.Instance.NumbersQueue.AddMessage(msg);
}
}
The worker role gets each of these message, and calculates the Collatz sequence:
I added a new feature in Azure.Library: a MessageProcessor that can consumes message from a queue, in its own thread:
public MessageProcessor(CloudQueue queue, Func<CloudQueueMessage, bool> process)
{
this.queue = queue;
this.process = process;
}
public void Start()
{
Thread thread = new Thread(new ThreadStart(this.Run));
thread.Start();
}
public void Run()
{
while (true)
{
try
{
CloudQueueMessage msg = this.queue.GetMessage();
if (this.ProcessMessage(msg))
this.queue.DeleteMessage(msg);
}
catch (Exception ex)
{
Trace.WriteLine(ex.Message, "Error");
}
}
}
public virtual bool ProcessMessage(CloudQueueMessage msg)
{
if (msg != null && this.process != null)
return this.process(msg);
Trace.WriteLine("Working", "Information");
Thread.Sleep(10000);
return false;
}
Then, the worker role is launching a fixed number (12) of MessageProcessor. In this way, each instance is dedicated to process many message. I guess that this is not needed in this example. But it was an easy “proof of concept” to test the idea. Part of Run method in worker role;
QueueUtilities qutil = new QueueUtilities(account);
CloudQueue queue = qutil.CreateQueueIfNotExists("numbers");
CloudQueueClient qclient = account.CreateCloudQueueClient();
for (int k=0; k<11; k++)
{
CloudQueue q = qclient.GetQueueReference("numbers");
MessageProcessor p = new MessageProcessor(q, this.ProcessMessage);
p.Start();
}
MessageProcessor processor = new MessageProcessor(queue, this.ProcessMessage);
processor.Run();
The ProcessMessage is in charge of the real work:
private bool ProcessMessage(CloudQueueMessage msg)
{
int number = Convert.ToInt32(msg.AsString);
List<int> numbers = new List<int>() { number };
while (number > 1)
{
if ((number % 2) == 0)
{
number = number / 2;
numbers.Add(number);
}
else
{
number = number * 3 + 1;
numbers.Add(number);
}
}
StringBuilder builder = new StringBuilder();
builder.Append("Result:");
foreach (int n in numbers)
{
builder.Append(" ");
builder.Append(n);
}
Trace.WriteLine(builder.ToString(), "Information");
return true;
}
The code of this example is in my
Next steps: more distributed apps (genetic algorithm, web crawler…)
Keep tuned!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez