Итак, у нас есть утечка памяти в нашем приложении, и мы думаем, что это из-за вызовов 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, так что проблем больше быть не должно, но я думаю, что есть...
FlushMemory
метод. Возьмите профилировщик памяти и найдите, что удерживает память. Не применяйте ненужную силуGC.Collect
, которая может привести к проблемам с производительностью. Вы можете использовать любой профилировщик памяти. Профилировщик ANTS или даже тот, который поставляется с Visual Studio. - person Sriram Sakthivel   schedule 26.03.2015