Ответ 1
Как вы указали, когда приложение настроено для работы в режиме GC рабочей станции, сборщик мусора не будет приостанавливать потоки, выполняющие собственный код. В этом случае в любое время, когда ваша служба получает запрос, я бы попробовал что-то вроде этого...
private bool _running = true;
private int _workCounter = 0;
private AutoResetEvent _workFlag = new AutoResetEvent(false);
private void RunNoGCNativeCode(params object[] args)
{
// Increase the work counter to determine how many requests are being processed
if (Interlocked.Increment(ref _workCounter) == 1)
{
// Try to start a No GC Region
GC.TryStartNoGCRegion(1 * 1024 * 1024 * 1024, true);
}
// TODO: Prep data and execute your native code
// TODO: Process response
// TODO: Dispose of anything that is no longer in use and null objects as needed
if (Interlocked.Decrement(ref _workCounter) == 0 && GCSettings.LatencyMode == GCLatencyMode.NoGCRegion)
{
GC.EndNoGCRegion();
}
// Notify Manual Collection thread work has been completed
_workFlag.Set();
}
В другой теме...
private void WaitForNoWorkThenGC()
{
// Continue running thread while in use
while (_running)
{
// Wait for some work to be complete
_workFlag.WaitOne();
// If there is no work being processed call GC.Collect()
if (_workCounter == 0)
{
GC.Collect();
}
}
}
Это поможет вам контролировать, когда происходит GC, чтобы минимизировать влияние на ваше приложение.
Что касается управляемого кода, я не нашел никаких указаний на то, что .NET Garbage Collection может "оставить в покое" определенные потоки, выполняющие управляемый код. Все текущие режимы (Server, Workstation, Concurrent и т.д.) Сборки мусора приостанавливают выполнение всех потоков, выполняющих управляемый код при его выборе. Обратите внимание, что некоторые режимы GC могут иметь более короткую паузу в потоках, что также может помочь. Я попытался использовать TryStartNoGCRegion() в приложении С# в реальном времени также, и он игнорирует мой запрос всегда, потому что объем памяти, который я использую, я не мог найти способ указать только собирать после достижения предела Х-памяти.
Однако есть два возможных решения, которые вы можете изучить.
- Используя Уведомления о сборе мусора, чтобы отслеживать, когда GC приближается к полной сборке мусора. Потенциально, если вы освободите некоторую память вручную, прежде чем она достигнет точки сбора, вы можете избежать сбора мусора.
- Запускать разные типы запросов в отдельных процессах приложения? или передать их отдельным процессам приложений по мере их получения. Таким образом, каждое приложение не использует контекст, и сбор мусора будет обрабатываться отдельно.