2012-01-08 60 views
9

我想創建一個程序,它可以限制一個進程的CPU使用率,即使在計算機空閒時。 我已經設置了一個程序來設置進程的優先級,但是如果計算機是閒置,CPU使用率可以達到95%。 該過程中包含「元素」是,我要限制提前如何限制一個進程的CPU使用率

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); 
    } 

感謝進程...

+0

我認爲你的問題是特定於操作系統,應該被標記爲這樣。我相信你的程序不能在Linux上用'mono'進行編譯。所以你的問題是比特定語言更具體的操作系統。 – 2012-01-08 08:37:28

+3

如果計算機未被使用(即空閒),爲什麼一個進程使用95%的CPU是一個問題? – 2012-01-08 08:45:55

+1

如果選擇在做*無*之間,並實現有用的工作,爲什麼操作系統會選擇什麼都不做?讓進程使用更少的CPU的方法是有更高優先級的進程來做某件事。 – 2012-01-08 08:46:05

回答

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); 
     } 
    } 
} 
+2

這就是爲什麼我喜歡這個網站。我總是學習很多有趣的東西。 +1爲一些真棒信息! – Demolishun 2012-01-08 21:16:40

1

我不知道C#的確切命令,但它是一個命令,將控制權交還給操作系統。我認爲在C++中,這可能會延遲或睡眠。所以在C#中的等價調用會延遲代碼並將循環返回給操作系統。

+1

['Thread.Sleep()'](http://msdn.microsoft.com /en-us/library/system.threading.thread.sleep.aspx)就是你可能指的。 – 2012-01-08 08:43:57

+0

我想限制的過程不是由我創建的。它只是一個遊戲。 – 2012-01-08 08:44:21

+0

如果你想減慢遊戲速度,你需要知道速度是CPU還是時鐘限制。如果是時鐘限制,限制CPU使用率將無濟於事。 – 2012-01-08 10:07:28