处理的异常仍然被抛出?

时间:2013-11-01 00:13:36

标签: c# exception exception-handling try-catch

我的代码:

public void CPUStats()
{
    var cpuCounter = new PerformanceCounter("Processor", "% Processor Time", 
                                                                     "_Total");
    var ramCounter = new PerformanceCounter("Memory", "Available MBytes");
    ramCounter.NextValue();
    cpuCounter.NextValue();
    System.Threading.Thread.Sleep(1000);
    string cpusage = cpuCounter.NextValue().ToString();
    string ramusage = ramCounter.NextValue().ToString();

    //Occurs here v
    try
    {
        //exception thrown here v
        cpuLabel.Invoke((MethodInvoker)(() => cpuLabel.Text = "CPU: " + 
                                   cpusage.Remove(cpusage.IndexOf('.')) + "%"));
    }
    catch(ArgumentOutOfRangeException)
    {
        cpuLabel.Invoke((MethodInvoker)(() => cpuLabel.Text = "CPU: " + 
                                                                 cpusage + "%"));
    }

    ramLabel.Invoke((MethodInvoker)(() => ramLabel.Text = "Free RAM: " + 
                                                             ramusage + "mb"));
}

有时我的应用程序将在cpuLabel调用时停止并在我的代码中处理并修复它时抛出“ArgumentOutOfRangeException”。我尝试增加激活激活CPUStats()的线程的计时器,但无济于事。

为什么会发生这种情况?

3 个答案:

答案 0 :(得分:2)

问题是由此代码引起的:

cpusage.Remove(cpusage.IndexOf('.')

您需要确保cpusage的长度并包含'。'在试图打电话之前。删除。

您可以通过运行简单的应用测试来证明这一点:

        var cpuusage = "0";

        System.Diagnostics.Debug.WriteLine(cpuusage.Remove(cpuusage.IndexOf('.')));

这将抛出ArgumentOutOfRangeException异常。

如果您将代码修改为:

        var cpuusageforlabel = "CPU: ";
        if (!string.IsNullOrEmpty(cpuusage)) {
            var index = cpuusage.IndexOf('.');
            if (index != -1) {
                cpuusageforlabel += cpuusage.Remove(index);
            } else {
                cpuusageforlabel += cpuusage;
            }
        } else {
            cpuusageforlabel += "0";
        }
        cpuusageforlabel += "%";

   cpuLabel.Invoke((MethodInvoker)(() => cpuLabel.Text = cpuusageforlabel));

您解决了异常,并且不必将参数捕获到范围异常之外。

答案 1 :(得分:2)

更新:

抱歉,我应该仔细阅读您的代码。您的try-catch包装了委托调用,可能不在当前的线程上下文中。我想你想做的应该是:

public void CPUStats() {
    var cpuCounter= .. 

    ... 

    MethodInvoker m=() => {
        try {
            cpuLabel.Text="CPU: "+cpusage.Remove(cpusage.IndexOf('.'))+"%";
        }
        catch(ArgumentOutOfRangeException) {
            cpuLabel.Text="CPU: "+cpusage+"%";
        }
    };

    cpuLabel.Invoke(m);

    ... 
}

查看SynchronizationContextControl.InvokeRequired

如果有更好的方法来检查可能的错误,请再次避免使用try-catch


@ competent_tech的答案很好,但我想补充一点。

在某些情况下,try-catch块仍会抛出:

  1. 你没有抓到引发的确切异常

  2. 处理程序重新抛出原始异常

  3. 处理程序导致另一个异常

  4. 在你的情况下,它命中catch块并且没有重新抛出原始块,也就是说,它遇到了第三种情况:处理程序导致另一个异常。

    如果你可以解决问题导致异常并避免它,那么不要以这种方式设计它。

    先生。 Lippert写了一篇关于异常的好文章,你可能想看看:

    http://ericlippert.com/2008/09/10/vexing-exceptions/

答案 2 :(得分:0)

最可能的原因是cpusage为空或空或没有。因此,当您获得异常并尝试再次使用相同的变量时,您将获得第二个异常。

在使用前检查cpusage,并且不要按照您使用的方式使用catch