Getting Started
Architecture
Transports
Persistence
ServiceInsight
ServicePulse
ServiceControl
Monitoring
Samples

Cooperative cancellation

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

Starting with version 8, NServiceBus supports cooperative cancellation. This enables NServiceBus to participate in graceful shutdown of its host by exposing a cancellation token to abort potentially long-running operations both outside and inside the message processing pipeline.

Outside the message processing pipeline

Methods used outside the message processing pipeline have an optional CancellationToken parameter. This includes methods for starting and stopping endpoints, and methods used to send or publish messages from outside a message processing pipeline, such as a web application.

CancellationToken parameters should be forwarded to any method that accepts one. For example, within a web application controller:

public class TestController
{
    private IMessageSession session;

    public TestController(IMessageSession session)
    {
        this.session = session;
    }

    [HttpPost]
    public async Task Post(CancellationToken cancellationToken)
    {
        // CA2016: Forward the 'CancellationToken' parameter to methods
        await session.Send(new MyMessage());

        // No diagnostic
        await session.Send(new MyMessage(), cancellationToken);
    }
}

Enabling .NET source code analysis (enabled by default in projects targeting .NET 5 or later) is also recommended so that CA2016: Forward the CancellationToken parameter to methods that take one can identify locations where a CancellationToken should be forwarded, and offers a code fix which updates the analyzed code to forward the token.

By default, violations of this rule are shown only as informational messages, but the analyzer severity can be upgraded to a warning using an .editorconfig file:

[*.cs]
dotnet_diagnostic.CA2016.severity = warning

Inside the message processing pipeline

Inside a message handler or saga, a cancellation token from the incoming message processing pipeline is available on the IMessageHandlerContext as the context.CancellationToken property. The cancellation token was added to the context parameter to avoid making a breaking change to IHandleMessages, which would affect all message handlers and sagas.

Similarly, pipeline behaviors also contain a CancellationToken property on their respective context parameters.

Methods on IMessageHandlerContext such as Send() and Publish() do not accept a cancellation token. The token from the incoming message pipeline is implicitly routed to outgoing operations.

The context.CancellationToken should be forwarded to any other method that will accept it. An analyzer included with NServiceBus identifies locations where the token should be forwarded with a build warning. For example:

public class SampleHandler : IHandleMessages<MyMessage>
{
    public async Task Handle(MyMessage message, IMessageHandlerContext context)
    {
        // NSB0002: Forward the 'CancellationToken' property of the context parameter to methods
        await MyDatabase.Store(new MyEntity());

        // No diagnostic
        await MyDatabase.Store(new MyEntity(), context.CancellationToken);
    }
}

The analyzer also offers a code fix that will update the code to forward the token using the "light bulb" menu ( Ctrl + . ).

If cancellation is not a major concern for a project, the analyzer severity can be downgraded using an .editorconfig file:

[*.cs]
dotnet_diagnostic.NSB0002.severity = suggestion

Samples