Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Azure Worker Role Changes in SDK 2.4

DZone's Guide to

Azure Worker Role Changes in SDK 2.4

· Cloud Zone
Free Resource

Linkerd, the open source service mesh for cloud native applications. Get the complete guide to using Linkerd and Kubernetes to build scalable, resilient applications.

 It’s been quite a while since we’ve seen any significant (ok, really any) changes in the boilerplate template code Visual Studio generates for Azure Cloud Services (web or worker roles). For as long as I can remember, the code has looked like this:

public override void Run()
{
    // This is a sample worker implementation. Replace with your logic.
    Trace.TraceInformation("WorkerRole.23 entry point called");
 
    while (true)
    {
       Thread.Sleep(10000);
       Trace.TraceInformation("Working");
    }
}

Pretty basic, right?  Just do some work forever.  If there is a failure (i.e. an unhandled exception), it’ll bubble up and out of the Run method, effectively crashing the role and Azure will restart it. The problem with this is that it didn’t effectively handle the case when the role stops – when OnStop is called. If your code was doing something at the that time, too bad, so sad.  You’re done. Microsoft released some guidance way back in January 2013 on The Right Way to Handle Azure OnStop Events. Unless you knew of this blog post, or were really good at your Bing-fu, it was too easy to just use the Visual Studio generated code. And then something happens, your code doesn’t do what you think it should (even though it does exactly what it is told to do), and bad words are uttered silently, and feelings get hurt.

Staring with Azure SDK 2.4, there is new boilerplate code generated by Visual Studio.  Check this out:

public class WorkerRole : RoleEntryPoint
{
    private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
    private readonly ManualResetEvent runCompleteEvent = new ManualResetEvent(false);
 
    public override void Run()
    {
        Trace.TraceInformation("WorkerRole.24 is running");
 
        try
        {
            this.RunAsync(this.cancellationTokenSource.Token).Wait();
        }
        finally
        {
            this.runCompleteEvent.Set();
        }
    }
 
    public override void OnStop()
    {
        Trace.TraceInformation("WorkerRole.24 is stopping");
 
        this.cancellationTokenSource.Cancel();
        this.runCompleteEvent.WaitOne();
 
        base.OnStop();
 
        Trace.TraceInformation("WorkerRole.24 has stopped");
    }
 
    private async Task RunAsync(CancellationToken cancellationToken)
    {
       // TODO: Replace the following with your own logic.
       while (!cancellationToken.IsCancellationRequested)
       {
           Trace.TraceInformation("Working");
           await Task.Delay(7000);
       }
    }
}

At first blush, this looks more complicated. But it really isn’t that bad. In a way, it’s doing what that Microsoft blog post from 2013 was indicating, just using cancellation tokens.

The OnStop method is actually overridden in the template now. There, the cancellation token is triggered to indicate the running thread should be cancelled, and then wait for that to happen. In the RunAsync method, we’re just waiting for that cancellation request, otherwise continue doing some business. Easy.

Keep in mind that there is still the 5 minute limit to finish, or else Azure will terminate the process.

Linkerd, the open source service mesh for cloud native applications. Get the complete guide to using Linkerd and Kubernetes to build scalable, resilient applications.

Topics:

Published at DZone with permission of Michael Collier, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}