9

我有一个 .NET 通用主机,IHostedService它从 OPC-UA 接口接收事件并处理它们。

问题是,如果在处理一个事件的过程中发生了未处理的异常,整个应用程序就会崩溃

我阅读了文档,但没有找到有关全局异常处理程序或允许捕获未处理异常并防止应用程序崩溃的类似机制的任何信息。

是否有保护通用主机以及IHostedService防止未处理异常的解决方案?

编辑

我知道,这里最简单的事情是尝试/捕获异常而不是让它冒泡。但我想知道是否有类似 WinForms / WPF 中的机制,您可以在其中更全局地捕获此类异常并防止崩溃。

编辑

这是代码的简化版本:

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

    ...
}

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

4

2 回答 2

3

您可以添加应用程序域级别的事件处理程序,但您将无法控制以任何特定方式继续执行。为了能够控制执行以及它如何处理异常,您必须在处理 OPC 有效负载消息时实现 try/catch 语句。

于 2018-08-29T16:11:23.480 回答
1

您可以提供自定义IHostBuilderIHost实现来包装原始文件并捕获错误。

请参阅演示该方法并记录全局错误的此要点示例。

于 2021-06-29T09:30:36.723 回答