Làm thế nào để có được mức sử dụng CPU trong C #?


203

Tôi muốn có được tổng mức sử dụng CPU cho một ứng dụng trong C #. Tôi đã tìm thấy nhiều cách để đào sâu vào các thuộc tính của các quy trình, nhưng tôi chỉ muốn việc sử dụng CPU của các quy trình và tổng số CPU như bạn có trong Trình quản lý tác vụ.

Làm thế nào để làm điều đó?



36
Làm thế nào trên trái đất này là chủ đề ngoài? Nực cười.
Peter Moore

Câu trả lời:


205

Bạn có thể sử dụng lớp PerformanceCorer từ System.Diagnostics .

Khởi tạo như thế này:

PerformanceCounter cpuCounter;
PerformanceCounter ramCounter;

cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
ramCounter = new PerformanceCounter("Memory", "Available MBytes");

Tiêu thụ như thế này:

public string getCurrentCpuUsage(){
            return cpuCounter.NextValue()+"%";
}

public string getAvailableRAM(){
            return ramCounter.NextValue()+"MB";
} 

80
Đẹp - nhưng nguồn ban đầu dường như là từ đây: zamov.online.fr/EXHTML/CSharp/CSharp_927308.html
Matt Refghi

19
Từ những gì tôi phát hiện ra, tôi đã phải sử dụng cpuCorer.NextValue () hai lần và giữa chúng tôi phải ngủ (500)
Angel.King.47

Matt nói đúng Thậm chí bao gồm các lỗi, như quên từ khóa "trở lại".
Đánh dấu tại Ramp51

8
Vâng, nó trông giống như một bản sao từ liên kết đó, vì vậy một liên kết để tham khảo bản gốc sẽ có phong cách tốt đẹp. Mặt khác, CMS cũng rất hay khi cung cấp câu trả lời ở đây để các nhà phát triển lười biếng không phải tìm kiếm trên Google để tìm câu trả lời tương tự. : o)
BerggreenDK

13
Bạn sẽ cần gọi .NextValue hai lần, với một System.Threading.Thread. Cuộc gọi ngủ ở giữa (1000ms là đủ). Xem blog.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx để biết thêm thông tin về lý do tại sao điều này là bắt buộc, nhưng tóm tắt cấp cao là bạn cần hai mẫu để tính giá trị, và bạn cần cho HĐH một thời gian để có được cả hai điều này.
Cleggy

62

Nhiều hơn một chút so với yêu cầu nhưng tôi sử dụng mã hẹn giờ bổ sung để theo dõi và cảnh báo nếu mức sử dụng CPU là 90% hoặc cao hơn trong thời gian duy trì là 1 phút hoặc lâu hơn.

public class Form1
{

    int totalHits = 0;

    public object getCPUCounter()
    {

        PerformanceCounter cpuCounter = new PerformanceCounter();
        cpuCounter.CategoryName = "Processor";
        cpuCounter.CounterName = "% Processor Time";
        cpuCounter.InstanceName = "_Total";

                     // will always start at 0
        dynamic firstValue = cpuCounter.NextValue();
        System.Threading.Thread.Sleep(1000);
                    // now matches task manager reading
        dynamic secondValue = cpuCounter.NextValue();

        return secondValue;

    }


    private void Timer1_Tick(Object sender, EventArgs e)
    {
        int cpuPercent = (int)getCPUCounter();
        if (cpuPercent >= 90)
        {
            totalHits = totalHits + 1;
            if (totalHits == 60)
            {
                Interaction.MsgBox("ALERT 90% usage for 1 minute");
                totalHits = 0;
            }                        
        }
        else
        {
            totalHits = 0;
        }
        Label1.Text = cpuPercent + " % CPU";
        //Label2.Text = getRAMCounter() + " RAM Free";
        Label3.Text = totalHits + " seconds over 20% usage";
    }
}

7
Trường hợp getRAMCorer () ở đâu?
kiêng B

1
cpuCounter.NextValuetrả về afloat . Vậy tại sao lại gán nó cho a dynamic? Vậy thì tại sao lại trả lại dynamicnhư một object? Vậy thì tại sao phải cố gắng gán một objectcho một inttrong dòng int cpuPercent = getCPUCounter()? (Mã đó sẽ không được biên dịch.)
Wyck

21

Sau khi dành một chút thời gian để đọc qua một vài chủ đề khác nhau có vẻ khá phức tạp, tôi đã nghĩ ra điều này. Tôi cần nó cho một máy 8 lõi, nơi tôi muốn theo dõi máy chủ SQL. Đối với mã bên dưới, sau đó tôi chuyển vào "sqlservr" dưới dạng appName.

private static void RunTest(string appName)
{
    bool done = false;
    PerformanceCounter total_cpu = new PerformanceCounter("Process", "% Processor Time", "_Total");
    PerformanceCounter process_cpu = new PerformanceCounter("Process", "% Processor Time", appName);
    while (!done)
    {
        float t = total_cpu.NextValue();
        float p = process_cpu.NextValue();
        Console.WriteLine(String.Format("_Total = {0}  App = {1} {2}%\n", t, p, p / t * 100));
        System.Threading.Thread.Sleep(1000);
    }
}

Nó dường như đo chính xác% CPU đang được SQL sử dụng trên máy chủ 8 lõi của tôi.


Total_cpu phải là PerformanceCorer ("Bộ xử lý"), không phải PerformanceCorer ("Quá trình") .. nếu không, bạn chỉ nhận được 100% * số lõi.
steve nấu

3
Nơi nào bạn đặt donethành đúng? Trừ khi tôi đã bỏ qua một cái gì đó, điều này dường như là một vòng lặp vô tận:while(!done){...}
Manfred

@Manfred Đây thực sự là một vòng lặp vô tận
Jenny

16

Không sao, tôi hiểu rồi! Cảm ơn bạn đã giúp đỡ!

Đây là mã để làm điều đó:

private void button1_Click(object sender, EventArgs e)
{
    selectedServer = "JS000943";
    listBox1.Items.Add(GetProcessorIdleTime(selectedServer).ToString());
}

private static int GetProcessorIdleTime(string selectedServer)
{
    try
    {
        var searcher = new
           ManagementObjectSearcher
             (@"\\"+ selectedServer +@"\root\CIMV2",
              "SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor WHERE Name=\"_Total\"");

        ManagementObjectCollection collection = searcher.Get();
        ManagementObject queryObj = collection.Cast<ManagementObject>().First();

        return Convert.ToInt32(queryObj["PercentIdleTime"]);
    }
    catch (ManagementException e)
    {
        MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
    }
    return -1;
}

Thêm nhận tên máy chủ thay vì chọn Máy chủ đã tốt hơn. like this. chuỗi computername = Môi trường.GetEn MôiVariable ("tên máy tính");
Dave

9

Bạn có thể sử dụng WMI để lấy thông tin tỷ lệ phần trăm của CPU. Bạn thậm chí có thể đăng nhập vào một máy tính từ xa nếu bạn có quyền chính xác. Hãy xem http://www.csharphelp.com/archives2/archive334.html để có ý tưởng về những gì bạn có thể thực hiện.

Cũng hữu ích có thể là tham chiếu MSDN cho Win32_Process không gian tên .

Xem thêm một ví dụ về CodeProject Cách thực hiện: (Hầu hết) Mọi thứ trong WMI thông qua C # .


5

CMS có quyền, nhưng nếu bạn sử dụng trình thám hiểm máy chủ trong phòng thu trực quan và chơi xung quanh với tab bộ đếm hiệu suất thì bạn có thể tìm ra cách để có được nhiều số liệu hữu ích.


3

Điều này dường như hoạt động với tôi, một ví dụ cho việc chờ đợi cho đến khi bộ xử lý đạt tỷ lệ nhất định

var cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
int usage = (int) cpuCounter.NextValue();
while (usage == 0 || usage > 80)
{
     Thread.Sleep(250);
     usage = (int)cpuCounter.NextValue();
}

Tại sao bạn ngủ khi mức sử dụng bằng 0?
watashiSHUN

2

Lớp này tự động thăm dò bộ đếm cứ sau 1 giây và cũng là luồng an toàn:

public class ProcessorUsage
{
    const float sampleFrequencyMillis = 1000;

    protected object syncLock = new object();
    protected PerformanceCounter counter;
    protected float lastSample;
    protected DateTime lastSampleTime;

    /// <summary>
    /// 
    /// </summary>
    public ProcessorUsage()
    {
        this.counter = new PerformanceCounter("Processor", "% Processor Time", "_Total", true);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public float GetCurrentValue()
    {
        if ((DateTime.UtcNow - lastSampleTime).TotalMilliseconds > sampleFrequencyMillis)
        {
            lock (syncLock)
            {
                if ((DateTime.UtcNow - lastSampleTime).TotalMilliseconds > sampleFrequencyMillis)
                {
                    lastSample = counter.NextValue();
                    lastSampleTime = DateTime.UtcNow;
                }
            }
        }

        return lastSample;
    }
}

System.DateTimethực sự là một loại giá trị 8 byte, có nghĩa là các phép gán cho một DateTimebiến không phải là nguyên tử. Mã này không phải là luồng an toàn trên nền tảng 32 bit.
andrewjs

1

Tôi không muốn phải thêm vào gian hàng 1 giây cho tất cả các PerformanceCountergiải pháp. Thay vào đó tôi chọn sử dụng một WMIgiải pháp. Lý do tồn tại 1 giây chờ / gian hàng là để cho phép đọc chính xác khi sử dụngPerformanceCounter . Tuy nhiên, nếu bạn gọi phương thức này thường xuyên và làm mới thông tin này, tôi khuyên bạn không nên liên tục phải chịu sự chậm trễ đó ... ngay cả khi nghĩ đến việc thực hiện quy trình không đồng bộ để có được thông tin đó.

Tôi đã bắt đầu với đoạn trích từ đây Trả lại việc sử dụng CPU trong WMI bằng C # và thêm một lời giải thích đầy đủ về giải pháp trên bài đăng trên blog của tôi dưới đây:

Nhận mức độ sử dụng CPU trên tất cả các lõi trong C # bằng WMI


Vui lòng bao gồm câu trả lời ở đây thay vì liên kết đến blog của bạn.
Herman

@ Herman - Tôi không chỉ liên kết đến blog của mình; Tôi đã đưa ra lời giải thích đầu tiên, và tiến hành cung cấp một liên kết cho một câu trả lời sâu sắc ngoài bài viết ở đây.
atconway

giải pháp trong bài viết trên blog của bạn giống như 12 dòng mã. Tại sao không bao gồm điều đó trong câu trả lời của bạn ngoài việc cố gắng khiến mọi người ghé thăm blog của bạn?
Herman

@Herman - Vấn đề với việc nhấp vào liên kết là gì vì nó chứa một lời giải thích sâu sắc; đó là ý tưởng của phần 'tại sao'? Ngoài ra đây là 7 tuổi, chỉ cần nói. Phải nhớ bài đăng chính xác này và tôi là một người mới trên SO sau đó.
atconway

liên kết có thể bị hỏng và việc quét câu trả lời sẽ dễ dàng hơn nhiều khi nội dung cốt lõi là nội tuyến. Xin lỗi vì đã khắc nghiệt trong câu trả lời khác của tôi, tôi không ở đây để cho bạn một khoảng thời gian khó khăn. :)
Herman

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.