【问题标题】:How to control the CPU utilization of a thread at runtime?如何在运行时控制线程的 CPU 利用率?
【发布时间】:2014-11-14 13:38:01
【问题描述】:

以下代码是我的尝试。但是我确实明白这不是一种优雅的方法。有人可以指出我正确的方向。欢迎任何代码示例。感谢您的阅读。

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

}

【问题讨论】:

  • 我不知道能够准确指定您希望应用程序能够使用多少 CPU。我知道您可以设置特定线程的优先级,这将有助于限制进程的 CPU 使用率。关于Threads can be found here 的文档和关于设置Priority can be found here 的文档。我会确保这是您真正想做的事情,并且在这样做之前有一个特定的用例。
  • 'Application.DoEvents()' 循环 :((
  • @Cameron 所说的。如果线程正在做有用的工作,为什么要限制它们?如果他们没有做有用的工作,请更改设计,以免他们做无用的工作。如果他们正在做有用的工作,但它是 CPU 密集型的,因此无法接受地降低对 GUI 的响应或影响其他应用程序,请降低线程的优先级,以便它们只吸收其他线程执行后剩余的 CPU。哦 - 摆脱 DoEvents 循环 - 不需要这样的丑陋。替换为 Invoke/BeginInvoke 信号。
  • 并且不要设置池线程的优先级。这意味着使用QueueUserWorkItem、任何Task 线程、BackgroundWorker 等创建的线程。如果您需要设置优先级,则创建和管理您自己的线程(即Thread 类)。
  • @JimMischel - 如果设置池头的优先级(应该有 AfterCreation() 事件或一些覆盖 ctor 的虚拟方法),要么不切实际,要么不推荐,池设计者需要一记耳光:)

标签: c# c++ multithreading cpu-usage


【解决方案1】:

您可以通过创建作业对象来限制进程的 CPU 数量,您可以在其中通过 SetInformationJobObject 设置限制。在那里你需要填写结构JOBOBJECT_CPU_RATE_CONTROL_INFORMATION结构。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-22
    • 1970-01-01
    • 1970-01-01
    • 2012-03-19
    • 1970-01-01
    • 2012-07-16
    相关资源
    最近更新 更多