使用 PerformanceCounters 时获取 InvalidOperationException [关闭]

Posted

技术标签:

【中文标题】使用 PerformanceCounters 时获取 InvalidOperationException [关闭]【英文标题】:Getting InvalidOperationException when using PerformanceCounters [closed] 【发布时间】:2016-11-13 11:46:54 【问题描述】:

获取:

抛出异常:System.dll 中的“System.InvalidOperationException”

附加信息:

类别不存在。

代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication8

public partial class Form1 : Form

    PerformanceCounter cpuCounter;
    PerformanceCounter ramCounter;
    public Form1()
    
        InitializeComponent();
    
    int timeX = 0;
    private void timer1_Tick(object sender, EventArgs e)
    
        cpuCounter = new PerformanceCounter();
        cpuCounter.CategoryName = "Processor";
        cpuCounter.CounterName = "% Processor Time";
        cpuCounter.InstanceName = "_Total";


        float cpuUsage = 0.00F;
        cpuCounter.NextValue();
        cpuUsage = cpuCounter.NextValue();
        textBox1.Text = cpuUsage.ToString();


        ramCounter = new PerformanceCounter("Memory", "Available MBytes");
        float ram = ramCounter.NextValue();
        textBox2.Text = ram.ToString();

        chart1.Series["CPU Usage"].Points.AddXY(timeX, (int)cpuUsage);
        chart2.Series["Memory Use"].Points.AddXY(timeX, (int)ram);

    

    private void button1_Click(object sender, EventArgs e)
    
       timer1.Start();
    

    private void button2_Click(object sender, EventArgs e)
    
        timer1.Stop();
    


在每个.nextValue(); 上都出现错误

我尝试在CategoryName 中添加Processor Information,但也无济于事。

编辑: @Jim 这是我进行更改后的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
namespace WindowsFormsApplication12

public partial class Form1 : Form

    PerformanceCounter cpuCounter;
    PerformanceCounter ramCounter;

    public Form1()
    
        InitializeComponent();

        InitializeCounters();
    

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

       // ramCounter = new PerformanceCounter("Memory", "Available MBytes");
    

    int timeX = 0;
    private void timer1_Tick(object sender, EventArgs e)
    
        float cpuUsage = 0.00F;
        cpuUsage = cpuCounter.NextValue();
        textBox1.Text = cpuUsage.ToString();

        float ram = ramCounter.NextValue();
        textBox2.Text = ram.ToString();

        // Your chart stuff
        //chart1.Series["CPU Usage"].Points.AddXY(timeX, (int)cpuUsage);
        //chart2.Series["Memory Use"].Points.AddXY(timeX, (int)ram);
    

    private void button1_Click(object sender, EventArgs e)
    
        timer1.Start();
    

    private void button2_Click(object sender, EventArgs e)
    
        timer1.Stop();
    

【问题讨论】:

您能否至少给我们堆栈跟踪并解释一下您要做什么? 【参考方案1】:

每次计时器计时,您都在创建新的性能计数器,您只需初始化计数器一次

Form1 代码隐藏

PerformanceCounter cpuCounter;   
PerformanceCounter ramCounter;

public Form1()

    InitializeComponent();

    InitializeCounters();


private void InitializeCounters()

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

    ramCounter = new PerformanceCounter("Memory", "Available MBytes");


int timeX = 0;
private void timer1_Tick(object sender, EventArgs e)
        
    float cpuUsage = 0.00F;
    cpuUsage = cpuCounter.NextValue();
    textBox1.Text = cpuUsage.ToString();
   
    float ram = ramCounter.NextValue();
    textBox2.Text = ram.ToString();

    // Your chart stuff
    //chart1.Series["CPU Usage"].Points.AddXY(timeX, (int)cpuUsage);
    //chart2.Series["Memory Use"].Points.AddXY(timeX, (int)ram);


private void button1_Click(object sender, EventArgs e)

    timer1.Start();


private void button2_Click(object sender, EventArgs e)

    timer1.Stop();

旁注:

当不再使用计数器时,还要Dispose 计数器。也许在表单关闭事件中。

cpuCounter.Dispose();
ramCounter.Dispose();

结果


错误案例

如果我的示例仍然抛出错误,这很可能是因为您系统上的一个或多个性能计数器已损坏。

重建所有性能计数器:

打开命令提示符(具有管理员权限) 运行命令:lodctr /R

消息:

信息:成功重建性能计数器设置...

成功时会出现。

如果您收到消息:

无法从系统备份存储重建性能计数器设置,错误代码为 2

可能的解决方案:

关闭所有正在运行的程序 确保使用lodctr /R 和大写R 如果在目录 system32 中移动到目录 SysWOW64(使用 cd.. > cd syswow64)并在此目录中重试 lodctr /R 命令

【讨论】:

我尝试了你所说的,现在我得到一个 .NullReferenceException 和一个“对象引用未设置为对象实例”。 @Commongrate 我制作的示例将开箱即用。尝试创建一个新的 winforms 项目并添加与我的完全一样的代码进行测试。 (不要忘记调用InitializeCounters(); 来初始化计数器。在我的示例中,该方法是在 Form 构造函数中调用的。 我复制了您的代码,添加了所有内容并在 ramCounter = new PerformanceCounter("Memory", "Available MBytes"); 上运行它我得到了同样的“猫不存在”错误,所以我评论了它并运行它,它运行了,但是当我点击按钮 1 时它不会触发事件并且文本框是空的 编辑了帖子 @Commongrate 我自己进行了编辑,并添加了错误情况,尝试重建性能计数器。【参考方案2】:

在使用 PerformanceCounter 之前创建一个类别。更多细节和例子在msdn

    const String categoryName = "Processor";
    const String counterName = "% Processor Time";

    if ( !PerformanceCounterCategory.Exists(categoryName) ) 
    

        CounterCreationDataCollection CCDC = new CounterCreationDataCollection();

        // Add the counter.
        CounterCreationData ETimeData = new CounterCreationData();
        ETimeData.CounterType = PerformanceCounterType.ElapsedTime;
        ETimeData.CounterName = counterName;
        CCDC.Add(ETimeData);       

        // Create the category.
        PerformanceCounterCategory.Create(categoryName,
                "Demonstrates ElapsedTime performance counter usage.",
            PerformanceCounterCategoryType.SingleInstance, CCDC);
    

【讨论】:

以上是关于使用 PerformanceCounters 时获取 InvalidOperationException [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

流已经被操作或关闭,尝试创建Racers时获得了异常

运营商大数据实时获客

运营商大数据实时获客

.net 中性能计数器的初始化非常慢

为啥调用 PerformanceCounter 很慢?

如何使用性能计数器监控 WCF 服务正常运行时间?