WMI中的内存泄漏和可能的解决方案

时间:2015-03-26 09:08:42

标签: c# memory-leaks wmi

因此我们的应用程序中存在内存泄漏,我们认为它来自WMI调用。

这是我们认为是泄漏的代码:

private ThermalInfo()
{
    // ==============  Temperature

    var mgmtTempScope = new ManagementScope(@"\root\WMI");
    var oQuery = new ObjectQuery("select * from MSAcpi_ThermalZoneTemperature");
    ManagementObjectSearcher oTempSearch = null;
    ManagementObjectCollection collection = null;

    try
    {
        oTempSearch = new ManagementObjectSearcher(mgmtTempScope, oQuery);
        collection = oTempSearch.Get();

        foreach (var obj in collection)
        {
            mTemperature = Convert.ToDouble(obj.Properties["CurrentTemperature"].Value) / 10 - 273.2;
            mValid = true;
            obj.Dispose();
        }
    }
    catch //(Exception ex)
    {
        // Not supported
        mTemperature = 0;
        mValid = false;
    }
    finally
    {
        if (collection != null)
            collection.Dispose();
        if (oTempSearch != null)
            oTempSearch.Dispose();


        FlushMemory();
    }
}

这里是FlushMemory():

 [DllImportAttribute("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
        private static extern int SetProcessWorkingSetSize(IntPtr process, int minimumWorkingSetSize, int maximumWorkingSetSize);
        public static void FlushMemory()
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
            if (Environment.OSVersion.Platform == PlatformID.Win32NT)
            {
                SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1);
            }
        }

我们的应用程序(它实际上是一项服务)不断发展壮大 - 它唯一要做的就是调用此方法并设置mTemperatur和mValid。随着FlushMemory调用,泄漏停止,我可以整夜运行服务,而不会增加内存。 我现在唯一的问题是服务不再让自己停止。每当我想要停止服务时,它就永远不会停止,我总是不得不用taskkill或任务管理器强制停止它。

有人可以帮帮我吗?另外,我如何避免WMI调用中的泄漏?我已经获得了w8.1所以不应该再成为一个问题,但我想还有......

1 个答案:

答案 0 :(得分:0)

我们看到了类似的问题:即使正确使用了using(..){..}和Dispose(),ManagementClass等也会造成大量内存泄漏。 搜索stackoverflow和其他地方,这是一个常见问题。

一次调用 GC.WaitForPendingFinalizers()(属于上面FlushMemory()的一部分),足以修复它(不需要GC.Collect())

尽管我们并不真正认为它是一种解决方案,但这只是一种解决方法。