如何限制进程的CPU使用率

时间:2012-01-08 08:33:19

标签: c#

我想创建一个程序,即使计算机处于空闲状态,也可以限制进程的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);
    }

提前感谢...

2 个答案:

答案 0 :(得分:20)

如果您想要限制的程序不是您的,有几个选项:

  • 将进程优先级设置为Idle并且不限制CPU使用率,因为在任何情况下都应尽可能多地使用CPU。如果有一些有用的事情可以让你的CPU一直运行100%。如果优先级为idle,则如果另一个程序需要CPU,则此特定进程的CPU使用率将降低。
  • 如果您的系统是多核或多CPU,那么您可能需要设置processor affinity 。这将告诉您的程序只使用您希望他使用的处理器。例如,如果您的程序是多线程的并且能够消耗两个CPU的100%,那么将其亲和性设置为仅使用一个CPU。他的使用率仅为50%。
  • 最差选项,但实际上由90%的“CPU限制程序”实际使用,您可以在网上找到:测量进程的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 :(得分:1)

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