круговые зависимости между dlls с Visual Studio

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

Когда выполняются параллельные запросы, каждый из них создаст соединение и назначит его одной и той же переменной экземпляра, поэтому одно или несколько соединений будут потеряны и останутся открытыми. Использование этого DBConnection.getConnection / DBConnection.closeConnection позволяет предположить, что у вас также есть потенциальная утечка соединений.

Пожалуйста, прекратите использовать поля, чтобы сохранить ваши connection и statement, и вместо этого сделайте эти локальные переменные. Также рассмотрите возможность использования try-with-resources для правильного закрытия соединений и рассмотрите возможность использования DataSource напрямую вместо использования этой (вероятно, ненужной) абстракции DBConnection.

10
задан doppelgreener 16 September 2013 в 00:22
поделиться

7 ответов

Я глубоко сочувствую Вашей ситуации (как разъяснено Вашим редактированием), но как твердый сторонник выполнения корректной вещи, не вещи, которая работает на данный момент, если существует возможность вообще, я думаю, что необходимо осуществить рефакторинг эти проекты.

Решите проблему не признак.

7
ответ дан 3 December 2019 в 16:55
поделиться

Причина это работает над подобными Unix системами, состоит в том, потому что они выполняют фактическое разрешение соединения во время загрузки. Общая библиотека не знает, куда ее функциональное определение прибудет из того, пока она не будет загружена в процесс. Оборотная сторона этого - то, что Вы не знаете также. Библиотека может найти и вызвать функции в любой другой библиотеке (или даже основной двоичный файл, который запустил процесс во-первых). Также по умолчанию все в общей библиотеке экспортируется.

Windows не работает как этот вообще. Только явно экспортируемые вещи экспортируются, и весь импорт должен быть разрешен в разовой ссылкой библиотеке, который точка идентификационные данные DLL, который предоставит каждую импортированную функцию, был определен. Это требует, чтобы библиотека импорта связалась против.

Однако Вы можете (с некоторой дополнительной работой), обходят это. Использовать LoadLibrary для открытия любого DLL, Вы любите и затем используете GetProcAddress для определения местоположения функций, Вы хотите звонить. Таким образом, нет никаких ограничений. Но ограничения в нормальном методе там по причине.

Поскольку Вы хотите перейти от статических библиотек до DLLs, он кажется, что Вы предполагаете, что необходимо превратить каждую статическую библиотеку в DLL. Это не Ваша единственная опция. Почему бы не начинать перемещать код в DLLs только, когда Вы идентифицируете его как автономный модуль, который вписывается в многоуровневую структуру без зацикливания? Тем путем можно начать процесс теперь, но все еще напасть на него часть за один раз.

11
ответ дан 3 December 2019 в 16:55
поделиться

Как насчет этого:

Проект A

Общедоступный класс A реализует C.IA

Public Function foo(ByVal value As C.IB) As Integer Implements C.IA.foo
    Return value.bar(Me)
End Function

Класс конца

Проект B

Общедоступный класс B реализует C.IB

Public Function bar(ByVal value As C.IA) As Integer Implements C.IB.bar
    Return value.foo(Me)
End Function

Класс конца

Проект C

Public Interface IA
    Function foo(ByVal value As IB) As Integer
End Interface

Public Interface IB
    Function bar(ByVal value As IA) As Integer
End Interface

Проект D

Sub Main()

    Dim a As New A.A
    Dim b As New B.B

    a.foo(b)

End Sub
1
ответ дан 3 December 2019 в 16:55
поделиться

Не возможно сделать чисто. Поскольку они оба зависят друг от друга, если изменения, то B должен быть перекомпилирован. Поскольку B был перекомпилирован, он изменился и потребности, которые будут перекомпилированы и так далее.

Это - часть причины, круговые зависимости плохи и хотите ли Вы или нет, Вы не можете упустить это из обсуждения.

0
ответ дан 3 December 2019 в 16:55
поделиться

Visual Studio осуществит зависимости, вообще говоря, так как функциональные адреса могут измениться в недавно скомпилированном DLL. Даже при том, что подпись может быть тем же, выставленный адрес может измениться.

Однако, если Вы замечаете, что Visual Studio обычно удается сохранить те же функциональные адреса между сборками, затем можно использовать одну из "Только" настроек сборки Проекта (игнорирует зависимости). Если Вы делаете это и получаете ошибку о неспособности загрузить зависимость DLL, то просто восстанавливают обоих.

0
ответ дан 3 December 2019 в 16:55
поделиться

Вам необходимо разделить две библиотеки DLL, разместив интерфейсы и реализацию в двух разных библиотеках DLL, а затем использовать позднее связывание для создания экземпляра класса.


// IFoo.cs: (build IFoo.dll)
    interface IFoo {
      void foo(int i);
    }

    public class FooFactory {
      public static IFoo CreateInstance()
      {
        return (IFoo)Activator.CreateInstance("Foo", "foo").Unwrap();
      }
    }

// IBar.cs: (build IBar.dll)
    interface IBar {
      void bar(int i);
    }

    public class BarFactory {
      public static IBar CreateInstance()
      {
        return (IBar)Activator.CreateInstance("Bar", "bar").Unwrap();
      }
    }

// foo.cs: (build Foo.dll, references IFoo.dll and IBar.dll)
    public class Foo : IFoo {
      void foo(int i) {
        IBar objBar = BarFactory.CreateInstance();
        if (i > 0) objBar.bar(i -i);
      }
    }

// bar.cs: (build Bar.dll, references IBar.dll and IFoo.dll)
    public class Bar : IBar {
      void bar(int i) {
        IFoo objFoo = FooFactory.CreateInstance();
        if (i > 0) objFoo.foo(i -i);
      }
    }

Классы «Factory» технически не нужны , но гораздо приятнее сказать:

IFoo objFoo = FooFactory.CreateInstance();

в коде приложения, чем:

IFoo objFoo = (IFoo)Activator.CreateInstance("Foo", "foo").Unwrap();

по следующим причинам:

  1. Вы можете избежать "приведения" в коде приложения, что хорошо
  2. Если DLL в котором размещены изменения класса, вам не нужно менять всех клиентов, только фабрику.
  3. Автодополнение все еще работает.
  4. В зависимости от ваших потребностей вы должны вызывать библиотеки DLL с учетом языка и региональных параметров или подписанные ключом , и в этом случае вы можете добавить дополнительные параметры к вызову CreateInstance на заводе в одном месте.

- Кеннет Касаджян

0
ответ дан 3 December 2019 в 16:55
поделиться

Единственный способ обойти это «чисто» (и я использую этот термин вольно) - это исключить один статических зависимостей / зависимостей времени компоновки и измените их на зависимость времени выполнения.

Может быть, что-то вроде этого:

// foo.h
#if defined(COMPILING_BAR_DLL)
inline void foo(int x) 
{
  HMODULE hm = LoadLibrary(_T("foo.dll");
  typedef void (*PFOO)(int);
  PFOO pfoo = (PFOO)GetProcAddress(hm, "foo");
  pfoo(x); // call the function!
  FreeLibrary(hm);
}
#else
extern "C" {
__declspec(dllexport) void foo(int);
}
#endif

Foo.dll экспортирует функцию. Bar.dll больше не пытается импортировать функцию; вместо этого он разрешает адрес функции во время выполнения.

Используйте собственную обработку ошибок и улучшения производительности.

0
ответ дан 3 December 2019 в 16:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: