0

我在这里关注答案:

计算带宽

并按照他说的执行了一切。我的显示器是这样初始化的:

netSentCounter.CategoryName = ".NET CLR Networking";
netSentCounter.CounterName = "Bytes Sent";
netSentCounter.InstanceName = Misc.GetInstanceName();
netSentCounter.ReadOnly = true;

我可以正确地看到Misc.GetInstanceName()返回“MyProcessName [id]”。但是,我不断收到实例在指定类别中不存在的异常。

我的理解是,在您实际发送或接收之前,不会创建净发送/接收的类别。

我已经按照答案中的描述添加了 app.config,如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.net>
        <settings>
            <performanceCounters enabled="true" />
        </settings>
    </system.net>
</configuration>

为什么我仍然收到错误消息?

这是我的监控代码:

public static class Monitoring
{
    private static PerformanceCounter netSentCounter = new PerformanceCounter();

    //Static constructor
    static Monitoring()
    {
        netSentCounter.CategoryName = ".NET CLR Networking";
        netSentCounter.CounterName = "Bytes Sent";
        netSentCounter.InstanceName = Misc.GetInstanceName();
        netSentCounter.ReadOnly = true;
    }

    /// <summary>
    /// Returns the amount of data sent from the current application in MB
    /// </summary>
    /// <returns></returns>
    public static float getNetSent()
    {
        return (float)netSentCounter.NextValue() / 1048576; //Convert to from Bytes to MB
    }
}

还有我的杂项课:

public static class Misc
{

    //Returns an instance name
   internal static string GetInstanceName()
    {
        // Used Reflector to find the correct formatting:
        string assemblyName = GetAssemblyName();
        if ((assemblyName == null) || (assemblyName.Length == 0))
        {
            assemblyName = AppDomain.CurrentDomain.FriendlyName;
        }
        StringBuilder builder = new StringBuilder(assemblyName);
        for (int i = 0; i < builder.Length; i++)
        {
            switch (builder[i])
            {
                case '/':
                case '\\':
                case '#':
                    builder[i] = '_';
                    break;
                case '(':
                    builder[i] = '[';
                    break;

                case ')':
                    builder[i] = ']';
                    break;
            }
        }
        return string.Format(CultureInfo.CurrentCulture,
                             "{0}[{1}]",
                             builder.ToString(),
                             Process.GetCurrentProcess().Id);
    }

    /// <summary>
    /// Returns an assembly name
    /// </summary>
    /// <returns></returns>
    internal static string GetAssemblyName()
    {
        string str = null;
        Assembly entryAssembly = Assembly.GetEntryAssembly();
        if (entryAssembly != null)
        {
            AssemblyName name = entryAssembly.GetName();
            if (name != null)
            {
                str = name.Name;
            }
        }
        return str;
    }
 }

编辑:我已经从 Windows 中打开了资源监视器以查看问题所在。尽管将 app.config 设置为这样做,但计数器并未启动。

这是我看到的(在我的应用程序发送网络活动之前和之后)

在此处输入图像描述

并且名称不是我的方法返回的名称。我的方法返回“SuperScraper [appId]”,而在资源中它被称为“Superscraper.vshost.exe”。

所以我现在有两个问题:

-我的计数器没有在应用程序启动时启动 -名称是不同的

4

2 回答 2

4

好的,我终于想通了。列出的“计算带宽”步骤似乎已过时,对 .Net 4 不再有效。

我将解释整个过程,以便您也可以这样做。

首先,您需要将其添加到您的 app.config 中:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.net>
        <settings>
            <performanceCounters enabled="true" />
        </settings>
    </system.net>
</configuration>

在 .Net 4.0 之前,这使应用程序在启动时创建计数器(而不是例如,在应用程序发送请求时创建网络计数器)。在 .Net 4.0 中,这告诉它在使用计数器时创建计数器。IE。如果您不设置此项,则不会创建任何计数器。

现在这是我浪费大部分时间的地方。我的假设是错误的,即如果您创建一个与自然创建时具有相同名称的性能计数器,您将获得这些值。然而,所有这一切都是阻止真正的计数器出现。

所以这样做:

//In .Net 4.0 the category is called .NET CLR Networking 4.0.0.0 and not .NET CLR Networking
netSentCounter.CategoryName = ".NET CLR Networking 4.0.0.0";
netSentCounter.CounterName = "Bytes Sent";
netSentCounter.InstanceName = Misc.GetInstanceName();
netSentCounter.ReadOnly = false; //<==
netSentCounter.RawValue = 0;     //<==

简单地阻止真正的计数器。

您需要做的是以自然的方式启动它。最好的方法是在应用程序启动时简单地发送一个欺骗请求,然后使用以下命令“监听”性能计数器:

//Send spoof request here
netSentCounter.CategoryName = ".NET CLR Networking 4.0.0.0";
netSentCounter.CounterName = "Bytes Sent";
netSentCounter.InstanceName = Misc.GetInstanceName();
netSentCounter.ReadOnly = true;

最后一点。实例名称不再是ApplicationName[appId]。现在它是:

[ApplicationName].exe_p [appId]_r [the CLR id hosting your application]_ad[ApplicationDomain]

希望这可以节省一些时间!

于 2012-04-17T16:44:30.560 回答
2

好的,我尝试了您的示例。我还遇到了性能监视器中没有显示的计数器,但是在我更改ReadOnly和设置RawValue属性后它确实出现了:

netSentCounter.CategoryName = ".NET CLR Networking";
netSentCounter.CounterName = "Bytes Sent";
netSentCounter.InstanceName = Misc.GetInstanceName();
netSentCounter.ReadOnly = false; //<==
netSentCounter.RawValue = 0;     //<==

就我而言,我发现性能监视器中的实例名称采用以下格式:myapplicationname_pPID

因此,在我更改了您的 GetInstanceName 方法行之后

return string.Format(CultureInfo.CurrentCulture,
                         "{0}[{1}]",
                         builder.ToString(),
                         Process.GetCurrentProcess().Id);

return string.Format(CultureInfo.CurrentCulture,
                     "{0}_p{1}",                
                     builder.ToString().ToLower(), //<== dont miss ToLower()
                     Process.GetCurrentProcess().Id);

计数器看起来开始工作了。

这是参考如何添加和删除计数器实例

还可以考虑netSentCounter.RemoveInstance()在使用完后删除()计数器。

于 2012-04-17T12:52:45.983 回答