Оптимальный способ получить частную память рабочего набора в C # для конкретного экземпляра процесса - PullRequest
0 голосов
/ 02 мая 2019

Я создаю небольшое консольное приложение, которое принудительно закрывает процессы, использующие определенный объем памяти, и я изо всех сил пытаюсь заставить его работать должным образом, когда процессор уже использует большую часть своей мощности.

Всякий раз, когда я использую PerformanceCounter для получения памяти Private Working Set , я легко получаю следующее исключение:

Произошла одна или несколько ошибок

Мне кажется, что если я "прикреплю" PerformanceCounter к процессу, я больше не смогу просто .Kill () сделать это.Это, конечно, медленный процесс, даже для получения значений.

Когда я использую Диспетчер задач , я могу четко видеть использование памяти процессом.Если я перейду на вкладку «Подробности», то увижу, что столбец памяти фактически является значением «Частный рабочий набор».

Есть ли способ получить это значение более оптимальным и более быстрым способом?

Вот код, который я использую для получения частного рабочего набора через PerformanceCounter:

public static long GetPrivateWorkingSetMemoryOfProcess(Process process)
{
    long process_size = 0;
    String InstanceName = PerformanceCounterInstanceName(process);
    var counter = new PerformanceCounter("Process", "Working Set - Private", InstanceName, true);
    process_size = Convert.ToInt32(counter.NextValue()) / 1024;
    return process_size;
}

Поскольку PerformanceCounter использует имя процесса в качестве параметра, а не ID, яиспользуйте эту функцию, чтобы получить правильное имя процесса:

public static string PerformanceCounterInstanceName(this Process process)
{
    var matchesProcessId = new Func<string, bool>(instanceName =>
    {
        using (var pc = new PerformanceCounter("Process", "ID Process", instanceName, true))
        {
            if ((int)pc.RawValue == process.Id)
            {
                return true;
            }
        }
        return false;
    });

    string processName = Path.GetFileNameWithoutExtension(process.ProcessName);
    return new PerformanceCounterCategory("Process")
           .GetInstanceNames()
           .AsParallel()
           .FirstOrDefault(instanceName => instanceName.StartsWith(processName)
                                           && matchesProcessId(instanceName));
}

И вот где я хотел бы использовать его для уничтожения процесса, который использует определенное количество памяти:

//get Process By ID
Process processToClose = Process.GetProcessById(Convert.ToInt32(processid));

long processesPrivateWorkingSetMemoryUsage = GetPrivateWorkingSetMemoryOfProcess(processToClose);
Console.WriteLine("Process '" + processid + "' uses " + processesPrivateWorkingSetMemoryUsage.ToString() + " memory.");
if (processesPrivateWorkingSetMemoryUsage <= 8000)
{
    processToClose.Kill()
}

1 Ответ

0 голосов
/ 02 мая 2019

Вместо использования API обходной путь заключается в вызове следующей команды PowerShell в C #.

(Get-Counter "\Process(notepad)\Working Set - Private").CounterSamples |
    Sort-Object InstanceName |
        Format-Table InstanceName, @{Label="PrivateWorkingSet"; Expression={$_.CookedValue / 1MB}} -AutoSize

Здесь я выбираю блокнот в качестве примера.Вы можете вызвать эту команду для каждого процесса, чтобы проверить закрытый рабочий набор.

Завершить процесс:

Stop-Process -Name "notepad"

См. " Выполнение сценариев PowerShell из C # " " Get-Counter - Пример 14. Поиск процессов на компьютере с самыми большими рабочими наборами"

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...