.NET Generic Host: предотвращение сбоя приложения при необработанном исключении - PullRequest
0 голосов
/ 29 августа 2018

У меня есть .NET Generic Host с IHostedService, который получает события от интерфейса OPC-UA и обрабатывает их.

Проблема в том, что если во время обработки события возникает необработанное исключение, происходит сбой всего приложения

Я прочитал документацию, но не нашел ничего о глобальном обработчике исключений или подобном механизме, который позволяет перехватывать необработанное исключение и предотвращать сбой приложения.

Есть ли решение для защиты общего хоста, а также IHostedService от необработанных исключений?

EDIT

Я знаю, здесь самое простое - попытаться / поймать исключение и не дать ему всплыть. Но я хотел бы знать, существует ли подобный механизм, как в WinForms / WPF, где вы можете отлавливать такие исключения более глобально и предотвратить сбой.

EDIT

Это упрощенная версия кода:

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;
    }

    ...
}

В этом примере легко добавить блок try / catch в методе ProcessOpcEvent, но было бы здорово иметь механизм, позволяющий избежать полного сбоя приложения в такой ситуации.

1 Ответ

0 голосов
/ 29 августа 2018

Вы можете добавить обработчик событий уровня домена приложения, но не сможете контролировать выполнение, продолжая каким-либо конкретным образом. Чтобы иметь возможность контролировать выполнение и то, как он обрабатывает исключения, вы ДОЛЖНЫ реализовывать операторы try / catch при обработке сообщений полезной нагрузки OPC.

...