Question

We are looking through our code trying to identify high CPU usage, and I am looking at several areas where we use while loops. I would like to take the risk of infinite loops out of the code shown below, but I am not sure what the best solution would be.

IDictionaryEnumerator codeEnumerator = Resources.Error_Codes.ResourceManager.GetResourceSet(CultureInfo.CurrentCulture, true, true).GetEnumerator();
IDictionaryEnumerator messageEnumerator = Resources.Error_Messages.ResourceManager.GetResourceSet(CultureInfo.CurrentCulture, true, true).GetEnumerator();


bool codeDone = false;
bool messageDone = false;

while (codeEnumerator.MoveNext() && !codeDone)
{
    string value = codeEnumerator.Value.ToString();
    if (value == failedResponse.Code.ToString())
    {
        key = codeEnumerator.Key.ToString();
        codeDone = true;
    }
}

while (messageEnumerator.MoveNext() && !messageDone)
{
    if (messageEnumerator.Key.ToString() == key)
    {
        message = messageEnumerator.Value.ToString();
        messageDone = true;
    }
}
Was it helpful?

Solution

Assuming that the underlying sequence are finite, not infinite, (which you have said is the case) then the loops will not run forever.

Eventually you can be sure that one of the following things will happen:

  1. The if will be true for a given item, thus setting the boolean and breaking out of the loop.

  2. You will advance to the end of the sequence, thus resulting in MoveNext being false.

  3. An exception will be thrown from somewhere, such as from the underlying collection being modified by another thread, by a null value in the sequence, or anything else. As you have no try/catch, this will break you out of the loop.

In particular, since each iteration of the loop must advance the iterator (due to MoveNext) you can be sure that you will eventually end.

OTHER TIPS

Looking at your code and trying to figure out what your dictionaries are actually named, I think you're looking for something like this:

var key = Error_Codes.FirstOrDefault(kvp => kvp.Value.ToString = 
    failedResponse.Code.ToString()).Select(kvp => kvp.Key);
string message = string.Empty;
if(null != key)
    message = Error_Messages[key];

This assumes your dictionaries are Error_Codes and Error_Messages.

As Eric pointed out in the comments, there were issues with the way you were using iterators and dictionaries. This does away with the iterator problems, but this still isn't an ideal way to use dictionaries.

If you have a unique list of error messages and error code keys, then you could have a dictionary that maps the two together. Alternatively, you could combine the dictionaries with a common key set for the dictionary key, and a tuple of error codes and error messages as the dictionary values.

You could start a timer/other thread that sets a second contidion to false if the loop takes more than x time. But i dont think that this is a clean solution either.

You could add a counter that counts down in the while loop. Set the counter real high to a value like 100 or so and When the counter reaches zero, exit the loop. It means that its possible it might terminate before the operation is completely carried out, but it means it will eventually exit.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top