private Dictionary<int, string> GetStringTable(bool isHelp)
{
Dictionary<int, string> stringTable;
RegistryKey libraryKey;
libraryKey = Registry.PerformanceData;
try
{
string[] names = null;
int waitRetries = 14; //((2^13)-1)*10ms == approximately 1.4mins
int waitSleep = 0;
// In some stress situations, querying counter values from
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\009
// often returns null/empty data back. We should build fault-tolerance logic to
// make it more reliable because getting null back once doesn't necessarily mean
// that the data is corrupted, most of the time we would get the data just fine
// in subsequent tries.
while (waitRetries > 0)
{
try
{
if (!isHelp)
names = (string[])libraryKey.GetValue("Counter " + _perfLcid);
else
names = (string[])libraryKey.GetValue("Explain " + _perfLcid);
if ((names == null) || (names.Length == 0))
{
--waitRetries;
if (waitSleep == 0)
waitSleep = 10;
else
{
System.Threading.Thread.Sleep(waitSleep);
waitSleep *= 2;
}
}
else
break;
}
catch (IOException)
{
// RegistryKey throws if it can't find the value. We want to return an empty table
// and throw a different exception higher up the stack.
names = null;
break;
}
catch (InvalidCastException)
{
// Unable to cast object of type 'System.Byte[]' to type 'System.String[]'.
// this happens when the registry data store is corrupt and the type is not even REG_MULTI_SZ
names = null;
break;
}
}
if (names == null)
stringTable = new Dictionary<int, string>();
else
{
stringTable = new Dictionary<int, string>(names.Length / 2);
for (int index = 0; index < (names.Length / 2); ++index)
{
string nameString = names[(index * 2) + 1];
if (nameString == null)
nameString = String.Empty;
int key;
if (!Int32.TryParse(names[index * 2], NumberStyles.Integer, CultureInfo.InvariantCulture, out key))
{
if (isHelp)
{
// Category Help Table
throw new InvalidOperationException(SR.Format(SR.CategoryHelpCorrupt, names[index * 2]));
}
else
{
// Counter Name Table
throw new InvalidOperationException(SR.Format(SR.CounterNameCorrupt, names[index * 2]));
}
}
stringTable[key] = nameString;
}
}
}
finally
{
libraryKey.Dispose();
}
return stringTable;
}