我有一个在ASP.NET 3.5,NHibernate 2.2和Sprint .NET中运行的站点用于依赖关系注入。在我们的测试服务器上,一个相当奇怪的错误发生者,并且几乎每次都有多个用户在线时。问题发生之后,将为每个用户及其提出的每个请求显示此错误-直到执行IISRESET。那就一切都好了。

这是例外:

'count' must be non-negative.
Parameter name: count
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.ArgumentOutOfRangeException: 'count' must be non-negative.
Parameter name: count

Source Error:
[No relevant source lines]

Source File: c:\Windows\Microsoft.NET\Framework64\v2.0.50727\Temporary ASP.NET      Files\root\4bf9aa39\6dcf5fc6\App_Web_z9ifuy6t.6.cs    Line: 0

Stack Trace:
[ArgumentOutOfRangeException: 'count' must be non-negative.
Parameter name: count]
System.String.CtorCharCount(Char c, Int32 count) +10082288
Spring.Objects.Factory.Support.AbstractObjectFactory.GetObjectInternal(String name, Type requiredType, Object[] arguments, Boolean suppressConfigure) +3612
Spring.Objects.Factory.Support.AbstractObjectFactory.GetObject(String name) +75
Spring.Objects.Factory.Support.DefaultListableObjectFactory.GetObjectsOfType(Type type, Boolean includePrototypes, Boolean includeFactoryObjects) +365
Spring.Context.Support.AbstractApplicationContext.GetObjectsOfType(Type type, Boolean includePrototypes, Boolean includeFactoryObjects) +136
Spring.Context.Support.AbstractApplicationContext.GetObjectsOfType(Type type) +66


[ActivationException: Activation error occured while trying to get instance of type InfoTextService, key ""]
   Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key) in      c:\Home\Chris\Projects\CommonServiceLocator\main\Microsoft.Practices.ServiceLocation\ServiceLocatorImplBase.cs:57
Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance() in c:\Home\Chris\Projects\CommonServiceLocator\main\Microsoft.Practices.ServiceLocation\ServiceLocatorImplBase.cs:90
OurProjectsNamespace.Infrastructure.ObjectLocator.LocateService() +86

最佳答案

这确实是一个非常奇怪的错误。当您查看AbstractObjectFactory.GetObjectInternal的来源时,您将看到以下结构:

[ThreadStatic]
private int nestingCount;

protected object GetObjectInternal(...)
{
    const int INDENT = 3;
    bool hasErrors = false;
    try
    {
        nestingCount++;

        if (log.IsDebugEnabled)
        {
            log.Debug("msg" +
                new String(' ', nestingCount * INDENT));
        }

        // More code: Calls self recursively.
    }
    catch
    {
        nestingCount--;
        hasErrors = true;

        if (log.IsErrorEnabled)
        {
            log.Error("msg" +
                new String(' ', nestingCount * INDENT));
        }
    }
    finally
    {
        if (!hasErrors)
        {
            nestingCount--;
            if (log.IsDebugEnabled)
            {
                log.Debug("msg" +
                    new String(' ', nestingCount * INDENT));
            }
        }
    }
}


您看到的异常必须由三个new String(' ', nestingCount * INDENT)调用之一引发。当提供的值为负数时,将引发特定的string构造函数调用。因为INDENT是常量,所以在这种情况下nestingCount必须具有负值。 nestingCount是线程静态变量。线程静态变量始终使用其默认值(在这种情况下为0)初始化,并且不受其他线程的影响。此外,在此方法之外永远不会使用nestingCount

因为nestingCount是线程静态的,并且仅在该方法中使用,所以很难想象nestingCount会变为负数的情况。也许在异步(ThreadAbort)异常的情况下,但是即使这样,我也很难想象。另一种选择是其他人使用反射更改线程静态变量。

但是最大的问题是:如何解决这个问题?

解:

我只能想到的一件事就是以不记录调试信息的方式重新配置log4net。当禁止调试信息时,string(char, int)构造函数可能永远不会再被调用,这将隐藏问题。不是很漂亮,但可能有效。这可能行得通,因为AbstractObjectFactory使用log变量记录日志,该变量初始化如下:

this.log = LogManager.GetLogger(this.GetType());


您可以通过全局禁用log4net中的调试信息写入功能来实现此目的,或者,当您认为这太过强大时,可以通过将log4net配置为禁用类型为Spring.Objects.Factory.Support.DefaultListableObjectFactory的调试信息(实际上是导致异常的实例)来实现。

祝好运。

08-03 17:53