【问题标题】:How to limit CPU usage of a process如何限制进程的 CPU 使用率
【发布时间】:2012-01-08 08:33:19
【问题描述】:

我想创建一个程序,即使在计算机空闲时也可以限制进程的 cpu 使用率。

我做了一个设置进程优先级的程序,但是如果计算机空闲,cpu使用率可以达到95%。进程包含“元素”是我要限制的进程

private static readonly string[] RestrictedProcess = new[] { "element" }; 
static void ProcessChecker(object o)
{
    List<Process> resProc = new List<Process>();
    foreach(Process p in Process.GetProcesses())
    {
        string s = p.ProcessName;
        foreach(string rp in RestrictedProcess)
        {
            s = s.ToLower();
            if (s.Contains(rp))
                resProc.Add(p);
        }
    }

    foreach(Process p in resProc)
    {
        p.PriorityBoostEnabled = false;
        p.PriorityClass = ProcessPriorityClass.Idle;
        p.MaxWorkingSet = new IntPtr(20000000);
    }

    SetPowerConfig(resProc.Count > 0 ? PowerOption.GreenComputing : PowerOption.Balanced);
}

【问题讨论】:

  • 我认为您的问题是特定于操作系统的,应该这样标记。我相信你的程序在 Linux 上不能用mono 编译。因此,您的问题更多的是特定于操作系统而不是特定于语言。
  • 如果计算机没有在使用(即空闲),为什么一个进程使用95%的CPU是个问题?
  • 如果在什么都不做和做有用的工作之间做选择,为什么操作系统会选择什么都不做?让进程使用更少 CPU 的方法是让优先级更高的进程执行某些操作。
  • 然后告诉操作系统您要省电,并让它管理它,即访问电源选项控制面板。
  • 听起来你不想改变CPU进程的priority,而是throttle CPU。在这种情况下,正如 Damien 所说,使用电源选项将最大使用量从 100% 降低。在 Win 7 中,可以在这里找到:Control Panel\All Control Panel Items\Power Options

标签: c#


【解决方案1】:

如果您要限制的程序不是您的,有几种选择:

  • 将进程优先级设置为Idle,不要限制CPU使用率,因为无论如何都应该尽可能多地使用CPU。如果有一些有用的事情要做,让你的 CPU 一直 100% 运行是可以的。如果优先级为idle,那么如果另一个程序需要CPU,则该特定进程的CPU使用率将降低。
  • 如果您的系统是多核或多 CPU,那么您可能需要设置processor affinity。这将告诉您的程序仅使用您希望他使用的处理器。例如,如果你的程序是多线程的,并且能够 100% 消耗你的两个 CPU,那么将他的亲和力设置为只使用一个 CPU。他的使用率将仅为 50%。
  • 最差的选项,但实际上被 90% 的“CPU 限制程序”使用,您可以在 Web 上找到:测量进程的 CPU 使用率并定期暂停和恢复它,直到达到 CPU 使用率达到你想要的值。

要暂停/恢复不属于您的进程,您必须使用 P/Invoke(这需要有权访问该进程,因此如果您是 Windows Vista 或更高版本,请注意 UAC 以获得管理员权限):

/// <summary>
/// The process-specific access rights.
/// </summary>
[Flags]
public enum ProcessAccess : uint
{
    /// <summary>
    /// Required to terminate a process using TerminateProcess.
    /// </summary>
    Terminate = 0x1,

    /// <summary>
    /// Required to create a thread.
    /// </summary>
    CreateThread = 0x2,

    /// <summary>
    /// Undocumented.
    /// </summary>
    SetSessionId = 0x4,

    /// <summary>
    /// Required to perform an operation on the address space of a process (see VirtualProtectEx and WriteProcessMemory).
    /// </summary>
    VmOperation = 0x8,

    /// <summary>
    /// Required to read memory in a process using ReadProcessMemory.
    /// </summary>
    VmRead = 0x10,

    /// <summary>
    /// Required to write to memory in a process using WriteProcessMemory.
    /// </summary>
    VmWrite = 0x20,

    /// <summary>
    /// Required to duplicate a handle using DuplicateHandle.
    /// </summary>
    DupHandle = 0x40,

    /// <summary>
    /// Required to create a process.
    /// </summary>
    CreateProcess = 0x80,

    /// <summary>
    /// Required to set memory limits using SetProcessWorkingSetSize.
    /// </summary>
    SetQuota = 0x100,

    /// <summary>
    /// Required to set certain information about a process, such as its priority class (see SetPriorityClass).
    /// </summary>
    SetInformation = 0x200,

    /// <summary>
    /// Required to retrieve certain information about a process, such as its token, exit code, and priority class (see OpenProcessToken, GetExitCodeProcess, GetPriorityClass, and IsProcessInJob).
    /// </summary>
    QueryInformation = 0x400,

    /// <summary>
    /// Undocumented.
    /// </summary>
    SetPort = 0x800,

    /// <summary>
    /// Required to suspend or resume a process.
    /// </summary>
    SuspendResume = 0x800,

    /// <summary>
    /// Required to retrieve certain information about a process (see QueryFullProcessImageName). A handle that has the PROCESS_QUERY_INFORMATION access right is automatically granted PROCESS_QUERY_LIMITED_INFORMATION.
    /// </summary>
    QueryLimitedInformation = 0x1000,

    /// <summary>
    /// Required to wait for the process to terminate using the wait functions.
    /// </summary>
    Synchronize = 0x100000
}

[DllImport("ntdll.dll")]
internal static extern uint NtResumeProcess([In] IntPtr processHandle);

[DllImport("ntdll.dll")]
internal static extern uint NtSuspendProcess([In] IntPtr processHandle);

[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr OpenProcess(
    ProcessAccess desiredAccess,
    bool inheritHandle,
    int processId);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CloseHandle([In] IntPtr handle);

public static void SuspendProcess(int processId)
{
    IntPtr hProc = IntPtr.Zero;
    try
    {
        // Gets the handle to the Process
        hProc = OpenProcess(ProcessAccess.SuspendResume, false, processId);

        if (hProc != IntPtr.Zero)
        {
            NtSuspendProcess(hProc);
        }
    }
    finally
    {
        // Don't forget to close handle you created.
        if (hProc != IntPtr.Zero)
        {
            CloseHandle(hProc);
        }
    }
}

【讨论】:

  • 这就是我喜欢这个网站的原因。我总是学到很多有趣的东西。 +1 获取一些很棒的信息!
【解决方案2】:

我不知道 C# 的确切命令,但它将是一个将控制权交还给操作系统的命令。我认为在 C++ 中可能是延迟或睡眠会这样做。因此,C# 中的等效调用将延迟代码并将周期返回给操作系统。

【讨论】:

  • Thread.Sleep() 可能是您所指的。
  • 我要限制的进程不是我创建的。。只是个游戏。
  • 如果您想减慢游戏速度,您需要确定速度是否受 CPU 或时钟限制。如果它是时钟限制的,那么限制 cpu 使用是没有用的。
猜你喜欢
  • 2011-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-11
  • 1970-01-01
  • 2012-07-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多