c# - 备份捕获 EventHandler 中抛出的异常
问题描述
我有一个 C# 程序作为 Windows 服务运行,做一些网络恶作剧,我以为我已经设置了最后的“日志致命错误”处理设置。但是我遇到了一个边缘情况,服务最终死了,但躲过了那些捕获。:(
我相信这是由于代码在注册到 .NET 库事件的 EventHandler 中引发异常所致。
显然我可以(并且应该!)在我的处理程序中捕获异常,但我想了解这是如何避免我的后备错误处理,以及我是否可以添加一些更强大的后备日志记录,以确保我有一些日志记录来分析未来类似的静默错误。
相关代码的妙语并不十分复杂:
ServiceBase.Run(container.Resolve<MyProjectWindowsService>());
in a try ...catch
inProgram.Main()
MyProjectWindowsService : ServiceBase
是具有实现的服务对象OnStop()
。
NetworkChange.NetworkAvailabilityChanged += CodeThatThrows;
但是当那个异常被抛出时,触发器OnStop()
也不是。try...catch
我可以在调试器中得到它,它似乎没有去任何地方..它只是......停止。
如果需要,请参阅下面的更详细的程序详细信息。
如何在注册到外部库事件的事件处理程序中捕获和记录未处理的异常?
(另外......我在上面描述的行为是预期的行为,还是发生了一些奇怪的事情?)
程序EXE入口点:
using System;
using System.ServiceProcess;
using Autofac;
using Autofac.Extras.NLog;
using NLog;
namespace MyProject.Service
{
internal static class Program
{
private static readonly ILogger Logger = LogManager.GetCurrentClassLogger();
/// <summary>
/// The main entry point for the application.
/// </summary>
private static void Main()
{
try
{
// var container = ...DI Setup...
ServiceBase.Run(container.Resolve<MyProjectWindowsService>());
}
catch (Exception ex)
{
Logger.Error(ex, "Unexpected error");
}
finally
{
Logger.Info("==========================");
Logger.Info("WindowsService Stopped (2)");
Logger.Info("==========================");
}
}
}
}
服务对象
using System;
using System.ServiceModel;
using System.ServiceProcess;
using Autofac;
using Autofac.Integration.Wcf;
using NLog;
namespace MyProject.Service
{
public class MyProjectWindowsService : ServiceBase
{
private readonly ILogger _logger;
public DNSProxyWindowsService(ILogger logger)
{
ServiceName = Constants.SERVICE_NAME;
_logger = logger;
}
protected override void OnStart(string[] args)
{
_logger.Info("==============================");
_logger.Info("DNProxy WindowsService Started");
_logger.Info("==============================");
//Other Active setupsteps
}
protected override void OnStop()
{
try
{
//Other Active shutdown steps.
}
catch (Exception ex)
{
_logger.Error(ex, "Could not shut down service tidily");
}
finally
{
_logger.Info("==========================");
_logger.Info("WindowsService Stopped (1)");
_logger.Info("==========================");
}
}
}
}
EventListener 注册到并最终调用:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using NLog;
using Exception = System.Exception;
namespace DNSProxy.Service
{
public class NetworkService
{
public NetworkService()
{
}
public bool NetworkDetectionEnabled
{
set
{
if (value)
{
NetworkChange.NetworkAvailabilityChanged += OnNetworkAvailabilityChanged;
NetworkChange.NetworkAddressChanged += OnNetworkAddressChanged;
}
else
{
NetworkChange.NetworkAvailabilityChanged -= OnNetworkAvailabilityChanged;
NetworkChange.NetworkAddressChanged -= OnNetworkAddressChanged;
}
}
}
private void OnNetworkAddressChanged(object sender, EventArgs e)
{
CodeThatCanApparentlyThrow();
}
private void OnNetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
{
CodeThatCanApparentlyThrow();
}
}
}
解决方案
不幸的是,我只能推测为什么您的代码没有捕获到异常(并且我将这种推测保留在评论中)
但是有两个可能对您有帮助的事件,
AppDomain.UnhandledException - 这允许您为应用程序中的任何未处理异常注册一个全局处理程序。这是文档https://docs.microsoft.com/en-us/dotnet/api/system.appdomain.unhandledexception?view=netframework-4.8
TaskScheduler.UnobservedTaskException - 因为我不熟悉您正在使用的框架库的内部结构,所以我将其包括在内,但可能在某处发生了一些异步代码,这可能不会观察任务的结果。如果错误的任务(即抛出异常)从未等待或从未访问过 Result 属性,然后超出范围,因此它可以被垃圾收集;在未来某个不确定的时间点,它将被收集并抛出 UnobservedTaskException。订阅此事件,将让您处理这种情况。文档在这里
推荐阅读
- python - 无需线程即可同时运行 Kivy 和 DeepSpeech
- sql - 可以在 Entity Framework Core 中动态加入相关模型吗?
- asp.net - 带有剃须刀的引导轮播问题
- javascript - 当“元素不可交互”时如何使用 Selenium 将“值”设置为输入
- oracle19c - 有没有办法转置两个字符串并得到一个表格作为结果?
- java - 方法 insert(String, Pair
>) 对于 BSTMap 类型不明确 >> 错误 - qt - 如何在 qml 中将半径应用于 ApplicationWindow
- c# - 使用 Twilio 发送 Apple 静默推送通知
- swift - 扩展中符合protocl,如何初始化属性?
- python - 我什么时候应该考虑使用预训练模型 word2vec 模型权重?