Cmdlet实例持续多久?

对派生的 Cmdlet 的自定义实现会是什么样子感兴趣,真的想看看涉及多少工作。模拟了以下内容:

using System.Management.Automation;

namespace EMSEngineering
{
    [Cmdlet(VerbsDiagnostic.Test, "Cmdlet")]
    public class TestCmdlet : Cmdlet
    {
        static int nextIndex = 0;

        private int index = nextIndex;

        public TestCmdlet()
        {
            System.Console.WriteLine("instantiating {0}", index);
            nextIndex++;
        }

        ~ TestCmdlet()
        {
            System.Console.WriteLine("terminating {0}", index);
        }

        [Parameter(Mandatory = true, ValueFromPipeline = true)]
        public string[] SomeParameter { get; set; }

        protected override void BeginProcessing()
        {
            if (SomeParameter != null)
                WriteVerbose(string.Format("begin processing {0} params", SomeParameter.Length));
        }

        protected override void ProcessRecord()
        {
            foreach (string param in SomeParameter)
                WriteObject(string.Format("processing {0}", param));
        }

        protected override void EndProcessing()
        {
            if (SomeParameter != null)
                WriteVerbose(string.Format("end processing {0} params", SomeParameter.Length));
        }

        protected override void StopProcessing()
        {
            WriteVerbose("stop processing");
        }
    }
}

这里没什么特别的,但是在提示下调用时,我注意到了一些意想不到的事情。

PS E:usersbitbucketcrmcallBuild_PI> '1','2' | Test-Cmdlet
实例化 0
处理 1
处理 2
PS E:usersbitbucketcrmcallBuild_PI> '1','2' | Test-Cmdlet
实例化 1
处理 1
处理 2
PS E:usersbitbucketcrmcallBuild_PI> 退出
终止 1
终止 0

每次调用我的模拟 Cmdlet 都会启动一个新实例。他们只在我退出 shell 时才终止。我在一个更大的循环中尝试了这个,这个循环重复了 10 次或更多次。相同的结果 - 每次调用都有新实例,并且都在 shell 退出时终止。

所有 Cmdlet 都是这种情况吗?它们真的只是堆叠起来直到 shell 退出吗?我在实现中遗漏了什么吗?

回答

  • 实际上,对 cmdlet 的每次调用都会创建实现 .NET 类的新实例

  • 这些实例最终会被垃圾收集(时间不确定,收集可能需要几分钟的时间),但您可以通过显式调用.NET 垃圾收集器来强制同步处理:

    [GC]::Collect(); [GC]::WaitForPendingFinalizers()
    

笔记:

  • 默认情况下,垃圾收集器会定期运行,并且如上所述,可能需要几分钟才能真正释放给定对象;然而,垃圾收集器也在低内存情况下按需运行,甚至周期性运行的频率也取决于内存条件(另一种说法:没有固定频率) - 请参阅垃圾收集基础帮助主题了解更多信息。

    • 举一个频率可变性的例子:在进入PowerShell 会话后不久,内存压力明显更高,使得近乎即时的垃圾收集更有可能。
  • 某些情况下,cmdlet 实现实例的垃圾收集会立即发生:

    • 如果您通过-?:调用帮助Test-Cmdlet -?(虽然不是通过Get-Help Test-Cmdlet,这不需要实例化 cmdlet 类)。

    • 如果调用在语法上无效,例如尝试使用未知参数时;例如:Test-Cmdlet -NosuchParam

    • 其他的?


以上是Cmdlet实例持续多久?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>