【问题标题】:.NET Generic Host : Prevent application crash on unhandled exception.NET 通用主机:防止应用程序因未处理的异常而崩溃
【发布时间】:2018-08-29 16:05:20
【问题描述】:

我有一个带有IHostedService 的 .NET 通用主机,它从 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 块,但如果有一种机制可以避免在这种情况下完全应用程序崩溃,那就太好了。

【问题讨论】:

  • 你可能想看看这篇文章 (stackoverflow.com/questions/5762526/…)
  • 显示一些代码。否则你会得到理论陈述。
  • @RyanWilson 不幸的是,这篇文章没有帮助,因为我的应用程序不是 WinForms 应用程序,而是 .Net 核心控制台应用程序
  • 代码是什么样子的?
  • “[is there] a similar mechanism like in WinForms / WPF” – Yes and no: 异常会在请求管道中自动捕获,因此您的应用程序即使在尽管个别请求可能会失败。但是在 Program.cs 级别遇到的异常是应用程序无法自动恢复的异常。所以你将不得不处理这些。如果您的后台服务失败,那么应用程序应该如何处理呢? 必须确保后台服务运行没有问题(或者如果有问题,它必须在内部处理它们)。

标签: c# asp.net-core .net-core asp.net-core-hosted-services


【解决方案1】:

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

【讨论】:

  • 这是我担心的答案 :( 添加 try/catch 语句没什么大不了的,但最好有某种安全网。
  • 试试catch语句很简单
【解决方案2】:

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

请参阅此gist sample,该gist sample 演示了该方法并记录了全局错误。

【讨论】:

    猜你喜欢
    • 2012-10-25
    • 2014-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多