【问题标题】:Memory leak using Powershell Remote Calls in C#在 C# 中使用 Powershell 远程调用的内存泄漏
【发布时间】:2014-06-07 16:31:15
【问题描述】:

我有一个 Windows 服务,它正在执行大量交换远程调用以获取一些服务器信息。我注意到,只要时间过去,服务使用的内存就会开始增长,直到引发内存异常。我已经搜索过,看起来System.Management.Automation 中存在已知的内存泄漏,它不会释放调用 close 和/或 dispose 方法时创建的Runspace 的所有内存。我查看了一篇建议使用 RunspaceFactoryCreateOutOfProcessRunspace 的帖子,但不知道如何使用它。

这里是如何重现问题:(System.Management.Automation dll 引用)

for (int i = 0; i < 1000; i++)
{
    var runspace = RunspaceFactory.CreateRunspace();
    runspace.Open();
    runspace.Close();
    runspace.Dispose();
}

如果您运行此代码,您将看到内存是如何增加的。由于要求,尽可能保持连接打开不是一个好的解决方案。

您知道我该如何解决这个问题,即使使用RunspaceFactoryCreateOutOfProcessRunspace 方法或如何正确处理内存?

提前致谢

编辑

我在使用 V3 并将运行空间创建更改为使用 CreateRunspacePool 方法,看起来泄漏已经消失了。非常感谢你的帮助!

【问题讨论】:

  • 是的,您似乎遇到了问题。也许有一种解决方法。你用这个运行空间做什么?
  • @Manuel 为什么标题说问题出在 remote 调用上?你的 sn-p 只创建一个运行空间,它实际上不做任何 PS 调用,远程或本地。

标签: c# powershell memory memory-leaks runspace


【解决方案1】:

我可以在 PS v3.0 中看到问题,但在 PS v2.0 中看不到。这是我用来 看到这个(所有示例都在 PowerShell 中):

for() {
    $runspace = [runspacefactory]::CreateRunspace()
    $runspace.Open()
    $runspace.Close()
    $p = Get-Process -Id $PID
    '{0} {1}' -f $p.Handles, ($p.PrivateMemorySize / 1mb)
}

在上面的代码中,v3.0 中的句柄和内存似乎泄漏了。

只要 v2.0 没有这个问题,一种可能的解决方法可能是 使用 PS v2.0 启动服务,即PowerShell.exe -Version 2.0

如果这不可能,我可以考虑另外两种解决方法。其中之一不是 直接创建运行空间,但改用[powershell]。例如,这个 代码在 v3.0 中没有显示泄漏:

for() {
    $ps = [powershell]::Create()
    $p = $ps.AddCommand('Get-Process').AddParameter('Id', $PID).Invoke()
    '{0} {1}' -f $p.Handles, ($p.PrivateMemorySize / 1mb)
    $ps.Dispose()
}

如果适用,另一种解决方法可能是使用 [runspacefactory]::CreateRunspacePool()。这种方式也不显示 泄漏:

$rs = [runspacefactory]::CreateRunspacePool()
$rs.Open()
for() {
    $ps = [powershell]::Create()
    $ps.RunspacePool = $rs
    $p = $ps.AddCommand('Get-Process').AddParameter('Id', $PID).Invoke()
    '{0} {1}' -f $p.Handles, ($p.PrivateMemorySize / 1mb)
    $ps.Dispose()
}
#$rs.Close() # just a reminder, it's not called here due to the infinite loop

最后一个也运行得更快,因为运行空间可以重复使用。

【讨论】:

  • 我在 .NET 4.5.1 上的 PowerShell v4 上没有看到任何问题。第一个运行空间打开将私有字节推到 13,892K(在 GC 之后),在 1000 次迭代(和最终 GC)之后,私有字节为 14,076K。没有太大的颠簸〜184K。句柄数和线程数也很稳定。
  • 感谢您的回答!我会尝试这些解决方法并让您知道
  • 我在使用 V3 并将运行空间创建更改为使用 CreateRunspacePool 方法,看起来泄漏已经消失了。非常感谢:)
【解决方案2】:

我在使用v1 of System.Management.Automation 时也遇到了同样的问题。但问题已通过v3 of System.Management.Automation 解决,并将代码更改为使用CreateOutOfProcessRunspace method

这里是代码

            using (PowerShellProcessInstance instance = new PowerShellProcessInstance(new Version(4, 0), null, null, false))
        {

            using (var runspace = RunspaceFactory.CreateOutOfProcessRunspace(new TypeTable(new string[0]), instance))
            {
                runspace.Open();

                using (PowerShell powerShellInstance = PowerShell.Create())
                {
                    powerShellInstance.Runspace = runspace;

                    var filePath = GetScriptFullName(powerShellScriptType);
                    powerShellInstance.Commands.AddScript(File.ReadAllText(filePath));

                    var includeScript = GetIncludeScript();
                    powerShellInstance.AddParameters(new List<string>
                {
                    userName,
                    plainPassword,
                    includeScript
                });
                    Collection<PSObject> psOutput = powerShellInstance.Invoke();

                    // check the other output streams (for example, the error stream)
                    if (powerShellInstance.Streams.Error.Count > 0)
                    {
                        // error records were written to the error stream.
                        // do something with the items found.
                        var exceptions = "";
                        foreach (var error in powerShellInstance.Streams.Error)
                        {
                            exceptions += error.Exception + "\n";
                        }

                        throw new InvalidPowerShellStateException(exceptions);

                    }
                    return psOutput;
                }
            }
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-24
    • 1970-01-01
    • 2012-02-03
    • 2014-11-13
    • 1970-01-01
    • 2017-10-18
    相关资源
    最近更新 更多