9

I understand that in a Windows service, it is better to use Timer rather than Thread.Sleep(timeout). However, in all code examples I could find on the Internet that were handling Azure workers, it is Thread.Sleep(timeout) which is used instead of Timer.

Even the default code provided in the Worker project template in Visual Studio uses a Thread.Sleep:

public class WorkerRole : RoleEntryPoint
{
    public override void Run()
    {
        // This is a sample worker implementation. Replace with your logic.
        Trace.WriteLine("$projectname$ entry point called", "Information");

        while (true)
        {
            Thread.Sleep(10000);
            Trace.WriteLine("Working", "Information");
        }
    }
// ...
}

So far, I've been also using Thread.Sleep in my workers but without really understanding why. So my question is, why using Thread.Sleep(timeout) in Azure worker role rather than Timer? What is the difference between Windows service and Azure worker that leads to this difference in how we are supposed to conceive this kind of application? Is it good or bad to use Timer in Azure workers?

Any explanation with links to some resources explaining the fundamentals of this is welcome as I couldn't find anything so far.

Guillaume
  • 1,782
  • 1
  • 25
  • 42
  • This isn't really a Windows Azure-specific question. There's a [great StackOverflow answer](http://stackoverflow.com/questions/2822441/system-timers-timer-threading-timer-vs-thread-with-whileloop-thread-sleep-for) that goes into quite a bit of detail about the different timers. This applies to Windows Azure VMs as well, since they're Windows Server 2008 VMs. – David Makogon Mar 05 '12 at 11:53
  • Thanks for the link. It's interesting but I don't feel like it really answers my question. I understand Windows Azure is VMs as well but if it was _just_ VM, why not just using Windows Services? In which case, my question would not would not need to be. – Guillaume Mar 06 '12 at 04:32
  • Ah... Well, you can certainly use Windows Services. However, to use a Windows Service in Windows Azure, you'll need to do some work. Here's a [blog post](http://blogs.msdn.com/b/mwasham/archive/2011/03/30/migrating-a-windows-service-to-windows-azure.aspx) showing what's involved. It's much more straightforward to run your code within the events provided by a Windows Azure Worker or Web Role. See my [answer about this](http://serverfault.com/a/365054/99269) on ServerFault as well. – David Makogon Mar 06 '12 at 11:45
  • Yes, I know it's possible, but I don't wantto use Windows service :) My comment was just to point out that Windows Azure and Windows services are not the same thing and thus they may require to be conveived differently even if in the end it's indeed a Win2k8 under it. – Guillaume Mar 07 '12 at 04:34

1 Answers1

15

The purpose of the Thread.Sleep() loop is to keep the Run() method from exiting. If Run() exits, then your worker will restart. I don't know that you could accomplish that goal effectively with a Timer.

Most likely your CPU is wasting some tiny amount of time to wake up that thread every 1000 msecs in order to do nothing. I doubt it's significant, but it bugged me too. My solution was to wait on a CancellationToken instead.

public class WorkerRole : RoleEntryPoint {
    CancellationTokenSource cancelSource = new CancellationTokenSource();

    public override void Run()
    {
        //do stuff
        cancelSource.Token.WaitHandle.WaitOne();
    }

    public override void OnStop()
    {
        cancelSource.Cancel();
    }
}

This keeps the Run() method from exiting without wasting CPU time on busy waiting. You can also use the CancellationToken elsewhere in your program to initiate any other shutdown operations you may need to perform.

Brian Reischl
  • 7,216
  • 2
  • 35
  • 46
  • You mean even if I have a Timer that is set as a static field of my `WorkerRole` class and its `Elapsed` event has a method assigned to it, the thread will still exit once the `Run()` method is processed? – Guillaume Mar 07 '12 at 04:46
  • 1
    Yes, that is what the documentation says. If you try it, you will most likely see your role continuously start up, shut down, and restart. http://msdn.microsoft.com/en-us/library/windowsazure/microsoft.windowsazure.serviceruntime.roleentrypoint.run.aspx – Brian Reischl Mar 07 '12 at 15:32
  • 2
    How does the `Thread.Sleep(Timeout.Infinity)` solution stack up against waiting on the `WaitHandle`? And for that matter, why not just use a `ManualResetEvent`? It's more than likely the same thing. – casperOne Mar 15 '13 at 14:25
  • Ah, you're right that we should `Dispose` it to be clean. Though it probably won't make any real difference in this case, since the process is shutting down anyway. – Brian Reischl Mar 15 '13 at 16:55