如何在不更改app.config的情况下在桌面应用中启用Background Server GC?

时间:2016-11-02 00:16:33

标签: c# .net wpf garbage-collection .net-4.5.2

我负责管理许多用户在不同硬件上运行的WPF桌面应用程序。多个线程不断地通过大量数据流失。

启用.NET Framework 4.5 Background server garbage collection已经显示出显着的性能改进,但这需要花费更多的内存和不同的CPU使用模式。对于功能较弱的用户来说,这是一个潜在的问题,所以我想给那些最有利于选择加入服务器GC的用户,而不是强迫每个人使用。

到目前为止,我发现启用此功能的唯一方法是App.Config

<configuration>
  <runtime>
    <gcServer enabled="true"/>
  </runtime>
</configuration>

但是,大多数用户无权编辑此内容,因为该应用程序位于“程序文件”中,而且他们不是本地管理员。我理想的情况是一个友好的措辞选项,可以在启用服务器GC的情况下重新启动应用程序并记住他们的选择。

所以我的问题是:有没有人知道应用此设置的其他任何方式?

我知道它可能是一厢情愿的想法 - 但理想情况下是运行时的动态,或者可能是在流程上下文中设置的命令行参数或环境变量。 CoreCLR中存在complus_gcServer env variable的提示。

我已经阅读了有关全局系统设置的信息,可以在计算机上启用此设置,但我不想冒险影响任何其他应用并导致其他不利影响,我只希望这适用于我的应用。

作为最后的手段,我可​​以使用不同的配置文件和启动器部署两个EXE副本来选择要运行的正确版本,但这看起来很极端。

感谢阅读,欢迎任何想法!

1 个答案:

答案 0 :(得分:1)

这是另一个建议。完成后保持服务器GC启用。然后基于用户定义的设置强制GC运行,如果应用程序内存超过您确定为临界级别的特定阈值。

请注意,如果您遵循此路径,则有效地说明您对CLR执行垃圾收集的时间有了更好的了解。通常情况下,我发现CLR本身比我们干预时更好。

检查内存使用情况并在所有代或指定代中运行GC的代码

if (Math.Abs(DateTime.Now.Subtract(MemUsageLastCheckTime).TotalMinutes) > 5d)
{
    long UsedMemory;
    //UsedMemory = GC.GetTotalMemory(false); // Not as reliable
    UsedMemory = System.Diagnostics.Process.GetCurrentProcess().PagedMemorySize64;
    if (UsedMemory > 1073741824) // One GB in bytes 1 X 1024 X 1024 X 1024
    {
        GC.Collect(); // Collect all generations
        //GC.Collect(2,GCCollectionMode.Forced);; Or collect a specific generation and force it to run now
    }
    MemUsageLastCheckTime = DateTime.Now;
}