尝试捕获异常会导致高CPU使用率吗?

3

我正在总结这段代码。下面的代码在一个foreach循环中迭代了将近4000次。 在我的本地IIS上,它可以正常工作,但是在生产云服务器上,整个应用程序会崩溃。

try
{
    cell.Value = decimal.Parse(dr[dc.ColumnName].ToString());
}
catch
{
    cell.Value = dr[dc.ColumnName];
}

我的问题是:使用上述的Catch块会导致高CPU使用率吗?
附加信息: Catch被触发了4000次。

4
这就是为什么会有 decimal.TryParse 的原因。你可能需要单独进行空值检查,否则 .ToString() 可能会导致崩溃。 - Peter B
在代码中添加 try catch 不会带来性能开销。但是,当捕获到异常时就会有开销。它们应该用于捕获异常情况,而不是作为流程控制。这样做会导致你的提交无法通过许多代码审查,会导致性能下降,并且还会招来未来开发人员的不满。 - TheGeneral
4
“Throwing”(抛出异常)代价高昂,而“Catching”(捕获异常)则不然。只需使用 TryParse 函数即可。 - Panagiotis Kanavos
1
如果你想知道 CPU 时间都花在哪里了,使用性能分析器比试图猜测瓶颈和原因要更值得投资你(和其他人)的时间。 - Damien_The_Unbeliever
1
@Anup,现在所有的ASP.NET堆栈都支持数据绑定。不要一个一个地检索值,而是将您的网格绑定到数据表。如果cell.Value指的是Excel单元格,请使用例如Epplussheet.Cells.LoadFromDataTable()一次性加载整个表。 - Panagiotis Kanavos
显示剩余10条评论
1个回答

6
在代码中加入try-catch虽然会有一些性能成本,但是我认为可以忽略不计:在我的Core i7 x64机器上使用.NET 4.6.1 Release版本,每次“未捕获的try”只需要小于< 0.001 µs的时间。
但是如果需要“捕获”,那么性能成本就会相当高:每次“必须捕获的try”大约需要12.5 µs的时间,在我的Core i7机器上使用.NET 4.6.1 Release版本。只有在抛出和捕获异常的数量达到数万次时才会注意到这种差异。
总的来说,如果可以避免抛出和捕获异常,那么最好这样做,在这里可以使用decimal.TryParse来实现。
现在您需要单独进行空值检查,否则.ToString()仍可能导致崩溃。
重写后的代码:
var v = dr[dc.ColumnName];
var s = v?.ToString(); // or you might use: var s = v as string;
if (s != null && decimal.TryParse(s, out decimal d))
    cell.Value = d;
else
    cell.Value = v;

为什么要保留 ToString()?如果值是字符串,(string) 应该就足够了。如果不是,那它是什么类型呢?也许它已经是一个十进制数了? - Panagiotis Kanavos
假设dr是一个DataRow,那么dr[dc.ColumnName]会产生一个对象,而decimal.TryParse不接受该对象。如果该对象实际上是一个字符串,则.ToString()将简单地执行(string)。但这仍然是OP可能能够改进的地方。 - Peter B
类型检查可以避免昂贵的格式/解析循环和临时对象,无论装箱值是否为字符串。该值的实际选项是字符串、数值类型(可转换为十进制)或无效值。 - Panagiotis Kanavos
看起来你的答案不准确,请查看这个问题:[https://dev59.com/SnM_5IYBdhLWcg3wmkYK] - Menahem
我修改了我的答案,加入了一些时间计算。 - Peter B
移除 try catch 代码块并使用 TryParse 解决了我的性能问题。 - Anup

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接