简体   繁体   English

.NET 通用主机:防止应用程序因未处理的异常而崩溃

[英].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.我有一个带有IHostedService的 .NET 通用主机,它从 OPC-UA 接口接收事件并处理它们。

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 ?是否有保护通用主机以及IHostedService免受未处理异常的解决方案?

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.但是我想知道是否有类似 WinForms / WPF 的机制,您可以在其中更全局地捕获此类异常并防止崩溃。

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.在这个例子中,很容易在ProcessOpcEvent方法中添加一个 try/catch 块,但是如果有一种机制可以避免在这种情况下应用程序完全崩溃,那就太好了。

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.为了能够控制执行及其处理异常的方式,您必须在处理 OPC 有效负载消息时实施 try/catch 语句。

You can provide custom IHostBuilder and IHost implementations that wrap the originals and catch errors.您可以提供自定义IHostBuilderIHost实现来包装原始文件并捕获错误。

See this gist sample that demonstrates the approach and that logs global errors.请参阅此gist 示例,该示例演示了该方法并记录了全局错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM