4

我有一个 .NET Web 应用程序,它为许多非 UI 代码使用单独的类库。在这个库中有一个静态类,用于站点范围的配置信息。它在Application_Start事件期间被初始化。

我遇到了一个问题,因为这个关键的静态对象似乎间歇性地失去了它的状态——我认为是因为 DLL 出于某种原因正在被卸载。它可能几天都不会发生,也可能一天发生几次。但是,这种情况应用程序没有重新启动的情况下发生,因此结果是所有初始化的数据Application_Start都丢失了,导致各种问题。回收应用程序池或以其他方式重新启动应用程序可以修复它。

在我弄清楚发生了什么之后,我更改了代码,以便类库中的配置对象使用静态构造函数初始化自身,而不是在应用程序启动阶段。这引入了一些其他不值得讨论的复杂性,但我可以让它工作——我只是认为这是一个糟糕的架构,不应该是必要的。

Application_Start在应用程序的生命周期内保持其状态期间,我是否应该能够依赖加载的外部 DLL 中的静态对象?显然我不能 - 而且我不太清楚为什么 - 但我想知道我是否应该寻找 DLL 正在卸载的原因,或者只是接受它可以并且从不编写依赖于外部静态对象的代码主应用程序 DLL 保持其值。

这是 Application_Start 的样子。

Application_Start() {

    // asp.net routing
    ConfigureRoutes();

    // LF is the static config object in an outside dll
    // the LFFactory object implements session & database stuff that's context-specific
    // (e.g. this is initialized with a different implementation when testing).

    LF.Initialize(new SiteEnvironment.Web.LFFactory());

    // add custom view engine...
    ViewEngines.Engines.Clear();
    ... blah blah 

}
4

4 回答 4

1

不确定它是否解决了您的问题,但在 Web 应用程序中使用静态类特别困难。具有静态方法的类(静态或基于实例)很好,但静态属性和字段会造成严重破坏。您的数据将在 IIS 内的线程之间共享,并且数据将以看似随机的顺序被覆盖。

如果您尝试共享静态数据,请将这些数据放在您的 web.config 中或将其缓存在服务器上。如果数据是读/写的,则将其放入基于实例的对象中。

于 2012-12-03T17:46:03.250 回答
0

如果您主要将其用于配置数据,我建议您将该配置数据放入站点的 Web.config 文件中。您可以(应该?)然后将其包装在与您现在所拥有的类似的类中。然后该类可以包含一些访问器,它们读取配置文件并将结果存储到静态内存中。如果由于某种原因,数据丢失了,那么访问者应该不会有任何问题,只需从配置文件中重新加载即可。

我希望这就是你要找的。我不完全确定您正在加载什么类型的配置数据以及它是否可以表示/存储在 XML 配置文件中。

我会想象这个类看起来像下面这样:

public static class MyConfig
{
  static MyConfig() { LoadConfigData(); }

  public static string ConnectionString
  {
    get
    {
      if (_connectionString == null) { LoadConfigData(); } //assignment of static data done here
        return _connectionString;
    }
  }
  private static string _connectionString = null;

  // repeat for other config-settings...
}
于 2012-12-03T17:14:30.813 回答
0

在回答我上面的问题之前,或者知道你的静态成员是什么样子之前,我会在黑暗中拍摄并说当引用计数达到 0 时,静态对象同样容易消失,就像任何其他对象一样。

一个潜在的解决方案是维护对该对象的“保证”应用程序持久引用,即使您不通过该引用访问该对象:

// for each static property we need to keep in memory
Application.Add("MyClass.property", MyClass.property);

检索对象的两种方式之一:

// our object should always be accessible like this
Object a = Application["MyClass.property"];

// and because we've created an application-persistent reference to the property,
// it should also be accessible like this
Object b = MyClass.property;

只是一个假设的,在黑暗中拍摄的建议!

附录: 如果不能期望 Application_Start 知道它需要跟踪的每个静态对象,我建议使用反射迭代你的类的属性,随时添加每个静态属性。

于 2012-12-03T17:45:17.147 回答
0

你的方法是正确的。问题可能是应用程序池正在回收。这将丢失共享内存。您可以调整应用程序池何时以及是否回收。

于 2013-04-26T19:11:42.443 回答