Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET Generic Host : Prevent application crash on unhandled exception

I have a .NET Generic Host with an IHostedService that receives events from an OPC-UA interface and that process them.

The problem is that if an unhandled exception occurs during the processing of an event, the whole application crashes

I read the documentation but I didn't find anything about a global exception handler or a similar mechanism that allows to catch unhandled exception and prevent an application crash.

Is there a solution to protect the Generic Host, as well as the IHostedService against unhandled exceptions ?

EDIT

I know, here the simplest thing is to try/catch the exception and not let it bubble up. But I'd like to know if there is a similar mechanism like in WinForms / WPF, where you can catch such exceptions more globally and prevent a crash.

EDIT

This is a simplified version of the code:

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
        return new HostBuilder()
            .UseEnvironment(environmentName)
            .ConfigureLogging((hostContext, logging) =>
            {
                ...
            })
            .ConfigureAppConfiguration((hostContext, builder) =>
            {
                builder
                    .SetBasePath(Directory.GetCurrentDirectory())
                    .AddJsonFile("appsettings.json", true, true)
                    .AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", true, true)
                    .AddEnvironmentVariables();
            })
            .ConfigureServices((hostContext, services) =>
            {
                services.AddSingleton<IHostedService, OpcClientHostedService>();
                ...
            });
    }
}

public class OpcClientHostedService : IHostedService
{
    private readonly OpcConfiguration _opcConfiguration;
    private readonly ILogger _logger;
    private readonly OpcClient _opcClient;

    public OpcClientHostedService(OpcConfiguration opcConfiguration, ILogger<OpcClientHostedService> logger)
    {
        _opcConfiguration = opcConfiguration;
        _logger = logger;
        _opcClient = new OpcClient(opcConfiguration.ServerUri);
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Connecting to OPC server with URI '{0}'", _opcConfiguration.ServerUri);
        try
        {
            _opcClient.Connect();
        }
        catch (Exception ex)
        {
            _logger.LogCritical(ex, "Cannot connect to OPC server");
            throw;
        }
        _logger.LogInformation("Connection to OPC server is successful");

        CreateOpcObservable().Subscribe(async args => await ProcessOpcEvent(args));

        return Task.CompletedTask;
    }

    private async Task ProcessOpcEvent(OpcValueChangedEventArgs args)
    {
        await MethodThatCanThrowAnException(args); // If the exception is not handled, the whole application crashes!
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Disconnecting to OPC server");
        _opcClient.Disconnect();
        _logger.LogInformation("Disconnection to OPC server is successful");
        return Task.CompletedTask;
    }

    ...
}

In this example, it is easy to add a try/catch block in the ProcessOpcEvent method, but it would be great to have a mechanism to avoid complete application crash in this kind of situation.

like image 909
sroll Avatar asked Aug 29 '18 16:08

sroll


People also ask

What is UseExceptionHandler?

UseExceptionHandler(IApplicationBuilder, Action<IApplicationBuilder>) Adds a middleware to the pipeline that will catch exceptions, log them, and re-execute the request in an alternate pipeline. The request will not be re-executed if the response has already started. UseExceptionHandler(IApplicationBuilder, String)

How do you handle exceptions in .NET Core?

To handle exceptions and display user friendly messages, we need to install Microsoft. AspNetCore. Diagnostics NuGet package and add middleware in the Configure() method. If you are using Visual Studio templates to create ASP.NET Core application then this package might be already installed.

What happens with an unhandled exception C#?

An unhandled exception occurs when the application code does not properly handle exceptions. For example, When you try to open a file on disk, it is a common problem for the file to not exist. The . NET Framework will then throw a FileNotFoundException.


2 Answers

You can add an app domain level event handler but you won't be able to control execution continuing in any specific manner. In order to be able to control execution and how it handles exceptions you MUST implement try/catch statements when you process your OPC payload messages.

like image 83
T McKeown Avatar answered Sep 22 '22 04:09

T McKeown


You can provide custom IHostBuilder and IHost implementations that wrap the originals and catch errors.

See this gist sample that demonstrates the approach and that logs global errors.

like image 28
Piper Avatar answered Sep 23 '22 04:09

Piper