Управление статическими глобальными неуправляемыми ресурсами в многопоточном приложении - PullRequest
2 голосов
/ 13 февраля 2012

Мы столкнулись с проблемой управления ресурсами, с которой мы боролись в течение нескольких недель, и, хотя у нас наконец есть решение, оно все еще кажется мне странным.

У нас есть значительное количествокод взаимодействия, который мы разработали для унаследованной системы, которая предоставляет C API.Одна из многих особенностей этой системы заключается в том, что (по неизвестным причинам) «среда», которая, по-видимому, является областью действия, должна быть инициализирована до использования API.Тем не менее, он может быть инициализирован только один раз и должен быть «выключен», как только вы закончите с ним.

Мы первоначально использовали шаблон Singleton для достижения этой цели, но, поскольку мы используем эту систему внутри размещенной IISвеб-служба, наш AppDomain будет время от времени подвергаться переработке, что приведет к появлению «осиротевших» сред, в которых происходит утечка памяти.С момента завершения и (по-видимому) даже IIS-утилизации недетерминировано и трудно обнаружить во всех случаях, мы перешли на схему подсчета выбытия + реф, которая, кажется, работает хорошо.Тем не менее, делать подсчет ссылок вручную кажется странным, и я уверен, что есть лучший подход.

Есть мысли по управлению статическим глобальным одноразовым ресурсом в такой среде?

Вот примерная структураУправление окружающей средой:

public class FooEnvironment : IDisposable
{
  private bool _disposed;
  private static volatile int _referenceCount;
  private static readonly object InitializationLock = new object();

  public FooEnvironment()
  {
    lock(InitilizationLock)
    {
      if(_referenceCount == 0)
      {
        SafeNativeMethods.InitFoo();
        _referenceCount++;
      }
    }
  }

  public void Dispose()
  {
    if(_disposed)
      return;

    lock(InitilizationLock)
    {
      _referenceCount--;
      if(_referenceCount == 0)
      {
        SafeNativeMethods.TermFoo();
      }
    }

    _disposed = true;
  }
}

public class FooItem
{
  public void DoSomething()
  {
    using(new FooEnvironment())
    {
      // environment is now initialized (count == 1)
      NativeMethods.DoSomething();

      // superfluous here but for our purposes...
      using(new FooEnvironment())
      {
        // environment is initialized (count == 2)
        NativeMethods.DoSomethingElse();
      }
      // environment is initialized (count == 1)
    }
    // environment is unloaded
  }
}

Ответы [ 2 ]

0 голосов
/ 13 февраля 2012

Один из подходов, который вы можете рассмотреть, - это создание изолированного домена приложений для вашего неуправляемого компонента.Таким образом, он не будет осиротеть при утилизации домена приложений, размещенного на IIS.

0 голосов
/ 13 февраля 2012

Сначала я прыгаю в ноги, так как есть много неизвестных о вашей конкретной кодовой базе, но мне интересно, есть ли пробег в подходе, основанном на сеансах? У вас может быть (потокобезопасный) синглтон фабрики сеансов, отвечающий за инициализацию только одной среды и ее правильное расположение путем привязки его к событиям в ASP.NET AppDomain и / или аналогичным образом. Вам нужно будет внедрить эту модель сеанса в ваш API, чтобы все клиенты сначала установили сеанс, прежде чем делать какие-либо вызовы. Извиняюсь за неопределенность этого ответа. Если вы можете предоставить пример кода, возможно, я мог бы дать более конкретный / подробный ответ.

...