2014-11-14 121 views
0

以下代码是我的尝试。但我明白这不是一个优雅的方法。有人能指出我的方向是正确的吗?任何代码是受欢迎的。谢谢你的阅读。如何在运行时控制线程的CPU利用率?

snap shot of application

public partial class Form1 : Form 
{ 
    BackgroundWorker worker = new BackgroundWorker(); 
    delegate void SetTextCallback(string text); 

    public Form1() 
    { 
     InitializeComponent(); 
     worker.DoWork += new System.ComponentModel.DoWorkEventHandler(worker_DoWork); 
     worker.ProgressChanged += worker_ProgressChanged; 
     worker.WorkerReportsProgress = true; 
     worker.WorkerSupportsCancellation = true; 
     worker.RunWorkerAsync(Convert.ToInt32(numericUpDown_CPU.Value)); 
    } 

    void worker_ProgressChanged(Object sender, ProgressChangedEventArgs e) 
    { 
     double currentUtilization = (double)e.UserState; 
     this.BeginInvoke(new SetTextCallback(SetText), new object[] { currentUtilization.ToString() }); 
     textBoxCurrentUtilization.Text = currentUtilization.ToString(); 
    } 

    void worker_DoWork(Object sender, DoWorkEventArgs e) 
    { 
     int CPU_utilization = (int)e.Argument; 

     while (true) 
     { 
      if (worker.CancellationPending) 
       return; 

      Thread.Sleep(CPU_utilization); 
      int total = 0; 
      Process p = Process.GetCurrentProcess(); 
      foreach (ProcessThread pt in p.Threads) 
      { 
       total += pt.TotalProcessorTime.Milliseconds; 
       if (pt.Id == (int)AppDomain.GetCurrentThreadId()) 
       { 
        TimeSpan ts = pt.TotalProcessorTime; 
        double percentage = ((double)(ts.Milliseconds + 1)/total) * 100; 
        worker.ReportProgress(Convert.ToInt32(percentage), percentage); 
       } 
      } 
     } 
    } 

    private void numericUpDown_CPU_ValueChanged(object sender, EventArgs e) 
    { 
     worker.CancelAsync(); 

     while (worker.IsBusy) 
      Thread.Sleep(100); 

     int desiredUtilization = Math.Abs(Convert.ToInt32(100 - numericUpDown_CPU.Value)); 
     worker.RunWorkerAsync(desiredUtilization); //restart worker 
    } 

    void SetText(string text) 
    { 
     this.textBoxCurrentUtilization.Text = text; 
    } 

} 
+0

我不知道能够确切指定您的应用程序能够使用多少CPU。我知道你可以设置一个特定线程的优先级,这将有助于节制进程的CPU使用率。关于[线程的文档可以在这里找到](http://msdn.microsoft.com/en-us/library/system.threading.thread(v = vs.110).aspx)以及关于设置[Priority可以是在这里找到](http://msdn.microsoft.com/en-us/library/system.threading.thread.priority(v = vs.110).aspx)。我会确保这是你真正想做的事情,并且在这之前有一个特定的用例。 – Cameron 2014-11-14 13:51:02

+1

'Application.DoEvents()'循环:(( – 2014-11-14 14:25:52

+3

@Cameron说了什么,如果线程正在做有用的工作,为什么要试着扼杀它们?如果他们没有做有用的工作,改变设计,如果他们正在做有用的工作,但这是CPU密集型的,并且如此不可接受地降低了对GUI的响应或影响其他应用程序,那么降低线程的优先级,以便它们只会吸收其他线程之后留下的CPU已经执行了哦 - 并且摆脱了DoEvents循环 - 不需要这样的丑陋,用Invoke/BeginInvoke信号代替 – 2014-11-14 14:32:08

回答

1

您可以通过创建一个作业对象,您可以设置通过SetInformationJobObject限制限制CPU的数量为你的过程。你需要填写结构JOBOBJECT_CPU_RATE_CONTROL_INFORMATION结构。

此功能仅在Windows版本> = 8上可用。作为设置硬限制的替代方法,您还可以在CPU速率超出时注册回调。你可以例如如果您确定它们是CPU活动的主要来源,请暂停您的工作线程。