如果我的配置文件缺少log4net配置部分,为什么我的应用程序会挂起?

4

我有一个应用程序(控制台应用程序,自托管ASP.Net WebAPI),它在设置过程中调用 XmlConfigurator.Configure()

如果我的应用程序的 app.config 文件像这样:

<configuration>
    <configSections>
        <section name="log4net"
                 type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
    </configSections>

    <log4net>
    </log4net>
</configuration>

如果我删除空的<log4net>元素,它就会挂起:
<configuration>
    <configSections>
        <section name="log4net"
                 type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
    </configSections>
</configuration>

在过去使用log4net时,我没有在任何地方看到这种行为(它通常只会将消息“log4net:ERROR XmlConfigurator: Failed to find configuration section 'log4net' in the application's .config file.”发送到控制台)。

我是否做错了什么,还是我发现了一个log4net的错误?


我已经进行了广泛的调试。 有两种行为:

  1. 当我跨越XmlConfigurator.Configure()时,它会无限期地挂起。
  2. 可以跨过对XmlConfigurator.Configure()的调用,但然后应用程序似乎停滞不前。 如果我暂停执行并查看活动线程,则有一个线程陷入了log4net方法(例如ConfigureFromFile)。

无论哪种情况,都会使整个应用程序挂起。

以下是来自挂起线程的堆栈跟踪(以上述第二种情况为例):

stack trace


如果您逐步执行代码会发生什么? - default
可能不是log4net中的bug,而是MS配置解析器出了问题。 - Justin Harvey
你同意这是一个错误。在这种情况下,它可能会在某些静态构造函数中弹出,而你无法捕获它。 - H H
看起来你的log4net配置设置有误。我会发一份示例,展示我的log4net是如何在企业Web应用程序上运行的。 - MethodMan
卡顿问题很容易诊断。使用调试+中断所有操作,查看调用堆栈。如果这样还是无法解决问题,请在您的问题中发布相关信息。另外,NLog 是更好的端口。 - Hans Passant
@HansPassant:调用配置log4net的是应用程序的主线程,因此整个程序会挂起。(我也使用NLog,但这与一个使用log4net大量集成的旧遗留代码相关)。 - adrianbanks
3个回答

4
最终,我通过这篇博客文章找到了问题的根源。
问题归结于我的机器上安装了.Net 4.5。尽管我正在针对.Net 4.0进行开发,但由于.Net 4.5具有即插即用的特性,因此行为有所不同。
如果配置文件中没有空的<log4net>元素,log4net将想要写入标准错误以通知该元素为空。如果没有该元素,则不会发生日志记录。当发生日志记录时(在应用程序中与其他控制台使用不同的线程),它会遇到由于.Net 4.5中控制台初始化方式的更改引起的死锁问题(详见链接的博客文章)。

你能否详细解释一下你所接受的答案?请问你是如何解决这个问题的? - MikroDel
1
@MikroDel:我确保为我的应用程序配置了日志记录。这样,就不会有空的<log4net>元素,因此也就不会尝试将日志记录到控制台,这是死锁的原因。 - adrianbanks
谢谢您的回复。我有一个几乎相同的问题[question](https://dev59.com/FGQm5IYBdhLWcg3wnAKR),其中我有**web.config**和3个配置文件,用于调试,测试和发布。其中一个是空的。这可能是问题吗?无论如何,如果您有想法,请在我的问题中将其发布为答案。我会投票支持它,如果它解决了我的错误消息,我会接受它。 - MikroDel

0
尝试像这样做,我在我的.config文件中有这个设置后:
在您的页面中声明类似于此的内容。
private static log4Net.ILog _logger = log4net.LogManager.GetLoggger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);


  <log4net>
    <root>
      <level value="ALL"/>
      <appender-ref ref="LogFileAppender"/>
    </root>
    <appender name="LogFileAppender"  type="log4net.Appender.RollingFileAppender,log4net">
    <param name="File value="c:\Logs\SampleLog.txt"/>
    <param name="AppendToFile value="true"/>
    <rollingStyle value="Size"/>
    <maximumFileSize value="2MB"/>
    <staticLogFileName value="false"/>
    <datePattern value="yyyyMMdd"/>
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger -%message%newline"/>
      </layout>
    </appender>
  </log4net>

1
我可以通过配置使其工作,这不是问题。我更感兴趣的是,为什么它的行为与我过去使用log4net的每个应用程序都不同。 - adrianbanks
很抱歉,我可能一开始没有理解您的问题。 - MethodMan

0

你的配置告诉XmlConfigurator管理器有一个名为Log4Net的部分。 因此,你的XmlConfigurator尝试加载该部分并抱怨。
我敢说这是可以预料的。
如果你删除在configSections中声明的任何部分,你将得到与任何派生的Configuration类相同的行为。


我以前使用过其他应用程序,它们没有展示这种行为,包括那些配置了log4net但没有定义配置部分的应用程序。为配置部分定义处理程序并不意味着该部分必须存在。 - adrianbanks

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