The sample uses the Generic Host and the Microsoft.
NuGet package to host NServiceBus as a Windows Service using the Generic Host underneath.
Prerequisites
The sample has the following prerequisites:
- .NET 4.8 SDK
- PowerShell Core for Windows in case the sample is to be installed as a Windows Service
Running the sample as a console
In Visual Studio, press F5 to start the sample as a console application.
Running the sample as a Windows Service
- Install PowerShell Core on Windows
- Start PowerShell core with elevated permissions
- Run
dotnet publish
in the directory of the sample; for example:C:\
samples\ generic-host - Run
New-Service -Name WorkerTest -BinaryPathName "C:\
samples\ generic-host\ bin\ Debug\ net48\ publish\ GenericHost. exe" - Run
Start-Service WorkerTest
- Go to the Event Viewer under
Windows Logs\
and observe event log entries from sourceApplications GenericHost
with the following content
Category: MyMessageHandler
EventId: 0
Received message #{Number}
- Once done, run
Stop-Service WorkerTest
andRemove-Service WorkerTest
Microsoft.Extensions.Logging
library, the NServiceBus.MicrosoftLogging
community package should be used.Code walk-through
var builder = Host.CreateDefaultBuilder(args);
builder.UseWindowsService();
The snippet above shows how the host builder runs by default as a Windows Service. If the sample is started with the debugger attached, it uses the console's lifetime instead. To always use the console lifetime use the following code instead:
var builder = Host.CreateDefaultBuilder(args);
builder.UseConsoleLifetime();
Next, the builder configures NServiceBus using the NServiceBus.
package, including the critical error action that will shut down the application or service in case of a critical error.
builder.UseNServiceBus(ctx =>
{
var endpointConfiguration = new EndpointConfiguration("Samples.Hosting.GenericHost");
endpointConfiguration.UseTransport(new LearningTransport());
endpointConfiguration.DefineCriticalErrorAction(OnCriticalError);
return endpointConfiguration;
});
The critical error action:
private static async Task OnCriticalError(ICriticalErrorContext context, CancellationToken cancellationToken)
{
var fatalMessage =
$"The following critical error was encountered:{Environment.NewLine}{context.Error}{Environment.NewLine}Process is shutting down. StackTrace: {Environment.NewLine}{context.Exception.StackTrace}";
EventLog.WriteEntry(".NET Runtime", fatalMessage, EventLogEntryType.Error);
try
{
await context.Stop(cancellationToken).ConfigureAwait(false);
}
finally
{
Environment.FailFast(fatalMessage, context.Exception);
}
}
To simulate work, a BackgroundService called Worker
is registered as a hosted service:
return builder.ConfigureServices(services => { services.AddHostedService<Worker>(); });
The IMessageSession
is injected into the Worker
constructor, and the Worker
sends messages when it is executed.
class Worker : BackgroundService
{
private readonly IMessageSession messageSession;
public Worker(IMessageSession messageSession)
{
this.messageSession = messageSession;
}
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
{
try
{
var number = 0;
while (!cancellationToken.IsCancellationRequested)
{
await messageSession.SendLocal(new MyMessage { Number = number++ }, cancellationToken)
.ConfigureAwait(false);
await Task.Delay(1000, cancellationToken).ConfigureAwait(false);
}
}
catch (OperationCanceledException)
{
// graceful shutdown
}
}
}