Getting Started
Architecture
NServiceBus
Transports
Persistence
ServiceInsight
ServicePulse
ServiceControl
Monitoring

Cooperative cancellation

Component: NServiceBus
NuGet Package: NServiceBus (8.x)

Run the solution. A single console application starts up: Server.

Code walk-through

When the endpoint is started, a message is sent to the endpoint, which triggers a long-running message handler. The handler enters an infinite loop, logging a message every two seconds, by calling the async Task.Delay() operation. The CancellationToken provided by the message handling context object is passed to Task.Delay() to cancel the delay operation if the context.CancellationToken.IsCancellationRequested property is set to true.

The NServiceBus pipeline filters out the OperationCanceledException specifically when the CancellationToken.IsCancellationRequested property is set to true. Further details on this behavior can be found in the cancellation and catching exceptions documentation.
public async Task Handle(LongRunningMessage message, IMessageHandlerContext context)
{
    log.Info($"Received message {message.DataId}. Entering loop.");

    while (true)
    {
        log.Info("Handler still running. Press any key to forcibly stop the endpoint.");
        await Task.Delay(2000, context.CancellationToken);
    }
}

Once a key is pressed, a CancellationTokenSource is created, scheduling a cancel operation after one second. This cancellation token is then passed to the endpoint's stop command for cooperative cancellation. (See the blog post Cancellation in NServiceBus 8.)

var tokenSource = new CancellationTokenSource();
tokenSource.CancelAfter(TimeSpan.FromSeconds(1));
await endpointInstance.Stop(tokenSource.Token);

After one second, a signal is sent to the cancellation token, terminating the long running handler and forcibly shutting down the endpoint. If the handler were to complete its operation before the cancel signal is sent to the cancellation token, then the endpoint would gracefully shutdown.