0

我们正在查看我们的代码以尝试识别高 CPU 使用率,并且我正在查看我们使用 while 循环的几个区域。我想从下面显示的代码中冒无限循环的风险,但我不确定最好的解决方案是什么。

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;
    }
}
4

4 回答 4

5

假设底层序列是有限的,而不是无限的(你说的是这种情况),那么循环不会永远运行。

最终,您可以确定会发生以下情况之一:

  1. 对于给定的项目,这if将是真的,因此设置布尔值并打破循环。

  2. 您将前进到序列的末尾,从而导致MoveNext错误。

  3. 异常将从某个地方抛出,例如来自被另一个线程修改的底层集合、序列中的空值或其他任何东西。由于您没有尝试/捕获,这将使您脱离循环。

特别是,由于循环的每次迭代都必须推进迭代器(由于MoveNext),您可以确定您最终会结束。

于 2013-04-30T16:29:58.663 回答
0

查看您的代码并试图弄清楚您的字典的实际名称是什么,我认为您正在寻找这样的东西:

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];

这假设您的字典是 Error_Codes 和 Error_Messages。

正如 Eric 在评论中指出的那样,您使用迭代器和字典的方式存在问题。这消除了迭代器问题,但这仍然不是使用字典的理想方式。

如果您有一个唯一的错误消息列表和错误代码键,那么您可以有一个将两者映射在一起的字典。或者,您可以将字典与字典键的公共键集以及错误代码和错误消息的元组结合起来作为字典值。

于 2013-04-30T17:58:21.177 回答
-1

如果循环花费的时间超过 x 时间,您可以启动一个计时器/其他线程,将第二个条件设置为 false。但我也不认为这是一个干净的解决方案。

于 2013-04-30T16:20:17.540 回答
-2

您可以在 while 循环中添加一个倒计时的计数器。将计数器实际高设置为 100 左右的值,当计数器达到零时,退出循环。这意味着它可能会在操作完全执行之前终止,但这意味着它最终会退出。

于 2013-04-30T16:16:47.370 回答