问题描述:
在C#中使用PerformanceCounterCategory(性能计数器)数据读取时,会存在对该方法调用的线程可能无限挂起,可能出现该问题的原因如下:
- 性能计数器的读取需要枚举系统上的打印机,存在(无效/错误)的打印机或驱动
- 未安装IIS全家桶
相关StackOverflow:什么会使 PerformanceCounterCategory.Exists 无限期挂起?
解决方案:
在SignalR源码的解决方案:
设置一个超时期限。如果它无法加载,那么我们将放弃加载其余部分。
Github PR: https://github.com/SignalR/SignalR/commit/8adb268b458fec7abf0c9b53514e2a2cbac23799
private static bool PerformanceCounterExistsSlow(string categoryName, string counterName)
{
// Fire this off on an separate thread
var task = Task.Factory.StartNew(() => PerformanceCounterExists(categoryName, counterName));
if (!task.Wait(_performanceCounterWaitTimeout))
{
// If it timed out then throw
throw new OperationCanceledException();
}
return task.Result;
}
private static bool PerformanceCounterExists(string categoryName, string counterName)
{
return PerformanceCounterCategory.Exists(categoryName) &&
PerformanceCounterCategory.CounterExists(counterName, categoryName);
}
经过测试该方案虽然会使程序继续运行,但进程却无法结束(即使taskkill -pid),因为该线程仍然处于无限挂起的状态
相关GitHub issue https://github.com/StackExchange/StackExchange.Redis/issues/587
我的建议是做出策略应对,如通过配置文件决定是否使用性能计数器,当然性能计数器导致线程无限挂起始终是小概率事件,重装操作系统一般就可以解决