发送/接收的网络丢失
我在这里听到了答案:
计算带宽
并实施了他所说的一切。 我的监视器初始化如下:
netSentCounter.CategoryName = ".NET CLR Networking"; netSentCounter.CounterName = "Bytes Sent"; netSentCounter.InstanceName = Misc.GetInstanceName(); netSentCounter.ReadOnly = true;
我可以正确地看到Misc.GetInstanceName()
返回“MyProcessName [id]”。 但是,我不断得到实例在指定类别中不存在的exception。
我的理解是,在您实际发送或接收之前,不会创建网络发送/接收的类别。
我按照答案中的说明添加了app.config,如下所示:
为什么我仍然会收到错误?
这是我的监控代码:
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; } /// /// Returns the amount of data sent from the current application in MB /// /// 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); } /// /// Returns an assembly name /// /// 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”。
所以我现在有两个问题:
– 我的计数器没有在应用启动时启动 – 名称是不同的
好的,我终于明白了。 列出的计算带宽似乎已过时,不再适用于.Net 4。
我将解释整个过程,所以你也可以这样做。
首先,您需要将其添加到您的app.config:
在.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]
希望这能节省时间!
好的,我试过你的例子。 我还看到了在性能监视器中没有显示的计数器,但是在我更改了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()
)计数器。