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

9
我有一个使用.NET Generic Host的IHostedService,用于接收来自OPC-UA接口的事件并处理它们。但是问题在于,如果在处理事件过程中出现未处理的异常,整个应用程序将崩溃。
我查看了文档,但没有找到任何有关全局异常处理程序或类似机制的信息,可以捕获未处理的异常并防止应用程序崩溃。
是否有解决方法,以保护Generic Host和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块,但是最好有一种机制来避免完全的应用程序崩溃。

你可能想看一下这篇帖子(https://dev59.com/fm025IYBdhLWcg3w25uy) - Ryan Wilson
展示一些代码。否则你只会得到理论性的陈述。 - T McKeown
代码长什么样? - davidfowl
@davidfowl 我添加了一些简化的代码,但我认为它包含了所有相关部分。 - sroll
1
“[是否有]类似于WinForms / WPF的机制” - 是和不是:异常会自动在请求管道内捕获,因此即使个别请求失败,您的应用程序也会保持活动状态。但是,在Program.cs级别发生的异常是应用程序无法自动恢复的异常。因此,您将不得不处理这些异常。如果后台服务失败,那么应用程序可能如何处理呢?_您_必须确保后台服务无问题地运行(或者如果有问题,它必须在内部处理)。 - poke
显示剩余6条评论
2个回答

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

这就是我担心的答案 :( 添加try/catch语句并不是什么大问题,但最好有一些安全保障。 - sroll
1
Try catch语句很简单。 - T McKeown

2
你可以提供自定义的 IHostBuilderIHost 实现,包装原始实现并捕获错误。
请参阅此 示例代码片段,演示了这种方法并记录全局错误。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接