RawFraction performance counter persists its state

2019-07-08 08:16发布

问题:

I am creating and setting up the performance counters correctly but when I delete the category, recreate the category with the same name and add/update the counters to that category, it fails to update the counters and its values.

The following code runs fine for the first time but not the second time. The code to remove the "Delete category" is not needed right now but I want to be able to delete existing category each time we deploy our application.

How can I permanently delete the counter if its not doing so or reset its values?

    private PerformanceCounter mainCounter;
    private PerformanceCounter mainCounterBase;
    private string category = "TestPerformanceCounterTest";
    public void Test()
    {
                   //Counter setup

        if (PerformanceCounterCategory.Exists(category))
            PerformanceCounterCategory.Delete(category);
        if (!PerformanceCounterCategory.Exists(category))
        {
            var categoryCollection = new CounterCreationDataCollection();

            var counter1 = new CounterCreationData("RawCounter1", "", PerformanceCounterType.RawFraction);
            var counter2 = new CounterCreationData("RawCounterBase1", "", PerformanceCounterType.RawBase);
            categoryCollection.Add(counter1);
            categoryCollection.Add(counter2);


            PerformanceCounterCategory.Create(category, "", PerformanceCounterCategoryType.SingleInstance, categoryCollection);

            //  Wait and wait...
            Thread.Sleep(TimeSpan.FromSeconds(3));
        }
                    //create counters
                    mainCounter = new PerformanceCounter(category, "RawCounter1", false);
        mainCounterBase = new PerformanceCounter(category, "RawCounterBase1", false);
                    //reset values
                    mainCounter.RawValue = 0;
        mainCounterBase.RawValue = 0;

                    //update counter
                    mainCounter.IncrementBy(10);
        mainCounterBase.IncrementBy(20);
        **Console.WriteLine("Main counter: " +mainCounter.RawValue);//doesnt show value 50 the second time this is run**
        Console.WriteLine("Main counter Base: " + mainCounterBase.RawValue);
        Console.WriteLine("Main counter next value: " + mainCounter.NextValue());
        Console.WriteLine("Main counter base next value: " + mainCounterBase.NextValue());
    }

回答1:

I am pretty sure this is due to the way Windows manages performance data.

From MSDN, PerformanceCounterCategory.Create Method (String, String, PerformanceCounterCategoryType, CounterCreationDataCollection):

Note It is strongly recommended that new performance counter categories be created during the installation of the application, not during the execution of the application. This allows time for the operating system to refresh its list of registered performance counter categories. If the list has not been refreshed, the attempt to use the category will fail.

I don't have firsthand knowledge, but this suggests that the addition or deletion of categories is not a synchronous action.

To work around this, you might want to replace your first if with a while instead, like so:

while (PerformanceCounterCategory.Exists(category))
{
    PerformanceCounterCategory.Delete(category);
}

That's a little heavy-handed, though. Best recommendation is to not do the counter set up or tear down just before you need it. Instead, put it into an installer, or at the very least, create a separate tool to install/uninstall them. Also, you could create a Powershell script to install/uninstall them. See http://msdn.microsoft.com/en-us/library/windowsazure/hh508994.aspx for an example.