Утечка памяти в 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 Call утечка прекратилась, и я мог запускать службу всю ночь без какого-либо увеличения памяти. Единственная проблема, которая у меня есть сейчас, это то, что служба больше не позволяет себе останавливаться. Каждый раз, когда я хочу остановить службу, она никогда не останавливается, и мне всегда приходится принудительно останавливать ее с помощью Taskkill или диспетчера задач.

Может ли кто-нибудь помочь мне с этим? Также как я могу избежать утечки в вызовах WMI? У меня w8.1, так что проблем больше быть не должно, но я думаю, что есть...


person Flo    schedule 26.03.2015    source источник
comment
Стахп. Прекратите использовать этот FlushMemory метод. Возьмите профилировщик памяти и найдите, что удерживает память. Не применяйте ненужную силу GC.Collect, которая может привести к проблемам с производительностью. Вы можете использовать любой профилировщик памяти. Профилировщик ANTS или даже тот, который поставляется с Visual Studio.   -  person Sriram Sakthivel    schedule 26.03.2015
comment
Да - и я не могу найти никаких ссылок - и утечка происходит только тогда, когда мы используем вызовы WMI. FlushMemory удерживает нас на стабильном уровне 27 000 КБ, тогда как без FlushMemory он бесконечно увеличивается...   -  person Flo    schedule 26.03.2015


Ответы (1)


мы наблюдаем аналогичную проблему: ManagementClass и т. д. создают большую утечку памяти даже при правильном использовании использования (..) {..} и Dispose(). Поиск в stackoverflow и других местах, которые мы видим, является распространенной проблемой.

Однократного вызова GC.WaitForPendingFinalizers(), который является частью FlushMemory() выше, достаточно, чтобы это исправить (GC.Collect() не требуется)

хотя на самом деле мы не считаем это решением, а просто обходным путем.

person ac1965    schedule 14.12.2018