Handling application lifetime events for a hosted service

The IApplicationLifetime interface allows hosted services to gracefully handle startup and shutdown events. It has three properties of type CancellationToken.

  • ApplicationStarted
  • ApplicationStopping
  • ApplicationStopped

You can register callbacks for one or more of those notifications.

public HostedService(
  ILogger<HostedService> logger, 
  IApplicationLifetime applicationLifetime)
{
    _logger = logger;
    _applicationLifetime = applicationLifetime;
}

public Task StartAsync(CancellationToken cancellationToken)
{
    _logger.LogInformation("Entering StartAsync");

    _applicationLifetime.ApplicationStarted.Register(OnStarted);
    _applicationLifetime.ApplicationStopping.Register(OnStopping);
    _applicationLifetime.ApplicationStopped.Register(OnStopped);

    _timer = new Timer(
        ScheduledTask,
        this,
        TimeSpan.FromSeconds(3),
        TimeSpan.FromSeconds(3));

    return Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)
{
    _logger.LogInformation("Entering StopAsync");

    return Task.CompletedTask;
}

private void OnStarted()
{
    _logger.LogInformation("OnStarted called.");
}

private void OnStopping()
{
    _logger.LogInformation("OnStopping called.");
}

private void OnStopped()
{
    _logger.LogInformation("OnStopped called.");
}

The IApplicationLifetime interface also has a StopApplication method which unsurprisingly does just that, which is to terminate the current application.

private void ScheduledTask(object state)
{
    var source = state as HostedService;

    _logger.LogInformation($"ScheduledTask invocation {source._count} via timer.");

    if (source._count++ == 3)
    {
        _logger.LogInformation("Shutting down...");
        source._applicationLifetime.StopApplication();
    };
}

The screenshot below shows the order in which these notifications are fired. It’s quite intuitive and just as you’d expect.

IHostedService application lifetime

Advertisements

Generic hosted services in .NET Core using IHost and IHostedService

An approach used to simulate a long running or permanently running background task for cloud services is to deploy a REST API, and to invoke end-points on the API from a cloud-native event handler (AWS Lambdas or Azure Functions). When migrating on-prem Windows services, people would take this approach when the other option would have been to host their service in a virtual machine (AWS EC2 or Azure VM). .NET Core 2.1 has introduced a simpler alternative via the IHost and IHostedService interfaces.

The core idea here is to use the ASP.NET Core framework but without the HTTP engine. The current long term goal is to make this the default (so in future, even web-apps will use the generic host mechanism). So from that perspective, it’s not a bad idea to start using it preemptively. Here’s a really simple fully functional ASP.NET Core generic host service. All it does it launch a timer proc every 5 seconds. Think of it as the equivalent of a scheduled task.

class MyHostedService : IHostedService
{
    public static async Task Main(string[] args)
    {
        await new HostBuilder()
            .ConfigureServices((context, services) =>
            {
                services.AddLogging();
                services.AddHostedService<MyHostedService>();
            })
            .ConfigureLogging((context, logging) =>
            {
                logging.AddConsole();
            })
            .UseConsoleLifetime()
            .Build()
            .RunAsync();
    }

    ILogger<HostedService> _logger;

    public MyHostedService(ILogger<HostedService> logger)
    {
        _logger = logger;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        new Timer(
            state => { _logger.LogInformation("Timer invoked"); },
            this,
            TimeSpan.FromSeconds(0),
            TimeSpan.FromSeconds(5));

        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }
}

VC++ 2015 – Lazy generators

If you have ever used iterators in C# or Visual Basic, then this is essentially the same thing. You would need to enable the new experimental /await compiler option, same as in the previous blog entry.

std::experimental::generator<int> evens(size_t count)
{
  using namespace std::chrono;

  for (size_t i = 1; i <= count; i++)
  {
    yield i * 2;
    std::cout << "yielding..." << std::endl;
    std::this_thread::sleep_for(1s);
  }
}

Calling this method would be fairly straightforward.

void main_yield()
{
  for (auto ev : evens(7))
  {
    std::cout << ev << std::endl;
  }
}

And here’s the expected output.

yield_demo_cpp

I added the console output to demonstrate the laziness of the generator.

VC++ 2015 – Using resumable functions

Visual C++ 2015 has a new compiler option called /await that can be used to write and call resumable functions. Do note that this is an experimental feature and even the associated headers are in an experimental sub-directory. There is no UI option to turn this compiler option in VS 2015, so you would need to manually add it via the Additional Options box under the C/C++ property page.

To compile the samples in this blog entry, you would need the following includes.

#include <thread>
#include <future>
#include <iostream>
#include <experimental\resumable>
#include <experimental\generator>

Here’s a simple example async method that sums two numbers. To demonstrate the async-nature of the call, I’ve added a sleep of 2 seconds to slow down the operation.

std::future<int> sum_async(int x, int y)
{
  using namespace std::chrono;

  return std::async([x, y] 
  {
    std::this_thread::sleep_for(2s);
    return x + y; 
  });
}

The async function will execute the function asynchronously, typically in a separate thread, and return a future that will hold the result of the call when it’s completed. Now, here’s how this method can be called.

std::future<void> call_sum_async(int x, int y)
{
  std::cout << "** async func - before call" << std::endl;
  auto sum = await sum_async(x, y);
  std::cout << "** async func - after call" << std::endl;
}

The await keyword calls that method asynchronously and waits until the method executes to completion. And then control goes to the next line of code. At least in the version of VC++ 2015 I tested this on, if you use await, the return type needs to be a future.

Now, here’s a calling method that invokes this caller method.

void main_async()
{
  std::cout << "<< main func - before call" << std::endl;
  auto result = call_sum_async(7, 9);
  std::cout << "<< main func - after call" << std::endl;

  {
    using namespace std::chrono;
    std::cout << "<< main func - before sleep" << std::endl;
    std::this_thread::sleep_for(3s);
    std::cout << "<< main func - after sleep" << std::endl;
  }

  result.get();
  std::cout << "<< main func - after get" << std::endl;
}

To show that the async method actually does execute asynchronously, I added a sleep block in the calling method. Here’s what the output looks like.

async_demo_cpp

Notice how the calling method continues to execute. And then once the async method has completed it returns control back to the main thread. The await keyword just makes it so easy to do this. You write your code just as you would write synchronous code, and all the async-ness is hidden from you. Well not really hidden, but handled for you smoothly.

Oh by the way, I am back to blogging after a bit of a hiatus. Expect to see me post far more frequently going forward.

VS14 CTP – Implement Pure Virtuals

This refactoring option implements stub-functions for all pure virtuals in one or all base classes. Here’s an example.

class Person
{
public:

  virtual std::string GetName() = 0;
  virtual void SetName(std::string) = 0;
};

class DbEntity
{
public:
  virtual int GetId() = 0;
  virtual void SetId(int) = 0;
};

class Employee : Person, DbEntity
{
public:
  Employee();
};

If you right click on a specific base class, you’ll get an option to just implement pure virtuals for that class. If you right click on the derived class name, you’ll get the option to implement all pure virtuals for all base types.

imppurevirts

This is what you’ll end up with (in the header).

class Employee : Person, DbEntity
{
public:
  Employee();
  // Inherited via Person

  virtual std::string GetName() override;

  virtual void SetName(std::string) override;

  // Inherited via DbEntity

  virtual int GetId() override;

  virtual void SetId(int) override;

};

Corresponding definitions (empty ones) will be generated in the cpp file.

VS14 CTP – Move Definition Location

The CTP adds a refactoring option to move a function definition from header to cpp, or vice-versa. Just right-click on the definition, choose Refactor/Move Definition Location and that’s it.

// h file
class Employee
{
public:
  Employee();

  int Foo(int x, int y);
};

// cpp file
Employee::Employee()
{
}

int Employee::Foo(int x, int y)
{
  return 0;
}

mdl01

Now your code looks like this.

class Employee
{
public:
  Employee();

  int Foo(int x, int y)
  {
    return 0;
  }
};

You can do the reverse too. There seems to be a bug in this CTP though – when you move from the h to the cpp, it does not prefix the class-name, so you get this.

int Foo(int x, int y)
{
  return 0;
}

I would assume that this would be fixed in the RTM.

Seemingly a minor feature, but it is convenient and once you get used to it, you’ll start to miss it when you don’t have it (when using an older version or a different IDE).

VS14 CTP – Create Declaration / Definition

The CTP 2 has a mostly stable implementation of the “Create Declaration / Definition” refactoring tool for your C++ projects. It lets you auto generate the definition or declaration of a member function. Example, if you have a class called Employee, declared in Employee.h and defined in Employee.cpp, you can type in a function declaration into the .h file and have the body auto-generated for you in the cpp file.

cdd02

You’ll get an empty definition.

int Employee::Foo(int x, int y, double d)
{
    return 0;
}

You can do the reverse too. Say you want to add an overload without the double paramater. Just copy paste this definition, remove the double paramater and then use the refactoring option.

cdd01

That’ll generate this for you.

int Foo(int x, int y);

Quite useful. That said, I wish it would do something like this. If I have code as follows.

Employee e;
e.Bar();

If you right click Bar() and choose this refactoring option, you’ll get a message that says – “The selected text does not contain any function signatures.”

Now that would have been handy. C# has had that for at least 2 iterations now.