如果存在延迟,使用BufferingTargetWrapper包装的NLog FileTarget无法写入日志

我可能偶然发现了NLog的一个问题,但我想先在这里查一下答案:

为了重新创建问题,我克隆了NLog源,因此我可以添加延迟来解决问题。 在visual studio中打开后,我添加了一个引用NLog源项目的控制台应用程序,并进行了一些非常简单的日志调用。 NLog.config如下:

          

到目前为止,所有工作都按预期进行。 下一步是在FileTarget的刷新逻辑中插入一个延迟。 (我发现这个问题的原因是我最初使用的MailTarget在连接到邮件服务器时会挂起一段时间 – 我已经将其替换为FileTarget ,而不是更容易重新创建问题)。

打开FileTarget.cs并找到Write(AsyncLogEventInfo[] logEvents)方法。 在第一行Thread.Sleep(5000)插入,以便方法如下所示:

 protected override void Write(AsyncLogEventInfo[] logEvents) { Thread.Sleep(5000); // ... omitted } 

现在,编译并重新运行。 日志没有写入。

据我所知,当进程退出时刷新所有目标的逻辑使用一个异步方法调用,默认超时为15秒,可以在LogFactory.cs Flush()方法中找到 – 显然没有超过。

但是,NLog使用ThreadPool.QueueUserWorkItem() (在AsyncHelpers.cs中找到)来并行编排每个目标的刷新。 这可以归结为一个问题,即这种forms的方法调用如何对Thread.Sleep()的调用或任何其他forms的阻塞(例如连接到远程服务器,如我原来的问题)做出反应?

有任何想法吗?

我终于弄清楚为什么没有记录任何内容,遗憾的是,没有什么可以做的。

根据AppDomain.ProcessExit的MSDN文档,这是NLog处理的事件:

所有ProcessExit事件处理程序的总执行时间都是有限的,就像所有终结器的总执行时间在进程关闭时受限一样。 默认值为两秒。 非托管主机可以通过使用OPR_ProcessExit枚举值调用ICLRPolicyManager :: SetTimeout方法来更改此执行时间。

因此,似乎从托管代码处理此问题的唯一方法是在允许应用程序退出之前手动调用LogManager.Flush()