Изтичане на памет в 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
Stahp. Спрете да използвате този FlushMemory метод. Вземете профайлър на паметта и намерете какво държи паметта. Не насилвайте ненужно GC.Collect, което е начин да предизвикате проблеми с производителността. Можете да използвате всеки профайлър на паметта. Профайлър на ANTS или дори този, който идва с визуално студио.   -  person Sriram Sakthivel    schedule 26.03.2015
comment
Да - и не мога да намеря задържане на никакви препратки - и изтичането се случва само когато използваме WMI извикванията. FlushMemory ни поддържа стабилни 27 000 kb, докато без FlushMemory тя се покачва безкрайно...   -  person Flo    schedule 26.03.2015


Отговори (1)


виждаме подобен проблем: ManagementClass и т.н. създава голямо изтичане на памет, дори при правилно използване на using(..){..} и Dispose(). Търсенето на stackoverflow и на други места, които виждаме, е често срещан проблем.

Еднократното извикване на GC.WaitForPendingFinalizers(), което е част от FlushMemory() по-горе, е достатъчно, за да се коригира (GC.Collect() не е необходим)

въпреки че не го смятаме за решение, а просто заобиколно решение.

person ac1965    schedule 14.12.2018