如何减少无限循环的风险
本文关键字:无限循环 何减少 | 更新日期: 2023-09-27 18:11:28
我们正在查看我们的代码,试图识别高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;
}
}
假设底层序列是有限的,而不是无限的(您已经说过是这种情况),那么循环将不会永远运行。
最终你可以肯定会发生以下其中一件事:
-
对于给定的项,
if
将为真,从而设置布尔值并跳出循环。 -
您将前进到序列的末尾,从而导致
MoveNext
为假 -
将从某处抛出异常,例如从底层集合被另一个线程修改,由序列中的空值或其他任何东西。由于没有try/catch,这将使您脱离循环。
特别是,由于循环的每次迭代都必须推进迭代器(由于MoveNext
),因此可以确定最终将结束。
查看你的代码并试图找出你的字典的实际名称,我想你会寻找这样的东西:
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在评论中指出的那样,您使用迭代器和字典的方式存在问题。这解决了迭代器的问题,但这仍然不是使用字典的理想方式。
如果您有一个唯一的错误消息列表和错误代码键,那么您可以有一个将两者映射在一起的字典。或者,您可以将字典与用于字典键的公共键集结合起来,并将错误代码和错误消息元组作为字典值。
可以启动一个timer/其他线程,如果循环时间超过x,则将第二个条件设置为false。但我也不认为这是一个干净的解决方案。
您可以在while循环中添加一个计数器。将计数器的实际高设置为100左右的值,当计数器达到零时,退出循环。这意味着它可能会在操作完全执行之前终止,但它意味着它最终会退出。