У меня есть простое приложение, которое создает пространство выполнения Powershell:
var iis = InitialSessionState.CreateDefault();
iis.ExecutionPolicy = ExecutionPolicy.Unrestricted;
iis.LanguageMode = PSLanguageMode.FullLanguage;
iis.ThreadOptions = PSThreadOptions.UseNewThread;
iis.DisableFormatUpdates = true;
m_Settings = new PSInvocationSettings
{
Host = new PSHostProxy(new PSUIStub()),
};
m_RunspacePool = RunspaceFactory.CreateRunspacePool(iis);
m_RunspacePool.CleanupInterval = new TimeSpan(0, 0, 10);
m_RunspacePool.SetMaxRunspaces(1);
m_RunspacePool.SetMinRunspaces(1);
m_RunspacePool.Open();
А затем использует его для выполнения нескольких скриптов PowerShell. Каждое RUN вызывается внешним событием (запускается в другом потоке) и происходит обычно через 20-50 секунд после предыдущего RUN:
RUN:
{
foreach(var scriptName in scripts)
{
var ps = PowerShell.Create();
ps.RunspacePool = m_RunspacePool;
var input = new PSDataCollection<string>();
ps.AddCommand(Path.Combine(scriptPath, scriptName));
ps.AddArgument(args);
// Call
ps.Invoke(input, m_Output, m_Settings);
...
m_Output.Clear();
input.Clear();
input.Dispose();
ps.Dispose();
ps = null;
}
}
И использование памяти продолжает расти во время выполнения, хотя сценарии всегда одинаковы, и даже их результаты одинаковы. Каждый цикл создает связку (как и тысячи из них, но я полагаю, что число определяется длиной исполняемых скриптов ...) SessionStateCmdLetEntry, и они никогда не удаляются и не GCed из-за ссылки TimerCallback, созданной RunspacePoolInternal. Это может занять до 1 ГБ памяти в день ...
У кого-нибудь есть советы, что еще я должен распорядиться или очистить, чтобы не хранить SessionStateCmdLetEntries? Или какие-нибудь обходные пути для этого?
Мне просто нужен длительный процесс, который вызывает несколько сценариев Powershell и не потребляет память. Я также пытался не использовать RunSpacePool повторно и создавать новое Runspace для каждого RUN и даже для каждого сценария, но он это сделал совсем не помогает ...
Спасибо за любую помощь ...