简体   繁体   English

处理的异常仍然被抛出?

[英]Exception that is handled is still thrown?

My code: 我的代码:

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"));
}

At times my application will stop at the cpuLabel invoke and throw an "ArgumentOutOfRangeException" when it was handled and fixed in my code. 有时我的应用程序将在cpuLabel调用时停止并在我的代码中处理并修复它时抛出“ArgumentOutOfRangeException”。 I tried increasing the timer that activates the thread that activates CPUStats(), but to no avail. 我尝试增加激活激活CPUStats()的线程的计时器,但无济于事。

Why would this happen? 为什么会这样?

The issue is being caused by this code: 问题是由此代码引起的:

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

You need to ensure that cpusage has length and contains a '.' 您需要确保cpusage具有长度并包含'。' before attempting to call .Remove. 在试图打电话之前。删除。

You can prove this by running a simple app test: 您可以通过运行简单的应用测试来证明这一点:

        var cpuusage = "0";

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

This will throw the ArgumentOutOfRangeException exception. 这将抛出ArgumentOutOfRangeException异常。

If you modify the code to be: 如果您将代码修改为:

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

You address the exception and won't have to catch the argument out of range exception. 您解决了异常,并且不必捕获超出范围异常的参数。

Update: 更新:

Sorry, I should read your code more carefully. 对不起,我应该仔细阅读你的代码。 Your try-catch wrapped the delegate invocation which may not in the current context of thread . 您的try-catch包含了委托调用,该调用可能不在当前的线程上下文中 I think what you want to do should be: 我想你想做的应该是:

public void CPUStats() {
    var cpuCounter= .. 

    ... 

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

    cpuLabel.Invoke(m);

    ... 
}

Have a look of SynchronizationContext and also Control.InvokeRequired . 看看SynchronizationContext以及Control.InvokeRequired

Again, avoid try-catch if there's a better way to check for possible errors. 再次,如果有更好的方法来检查可能的错误,请避免try-catch


@competent_tech's answer is good, but I'd like to add a little bit. @ competent_tech的答案很好,但我想补充一点。

There are some cases that a try-catch block would still throw: 在某些情况下, try-catch块仍会抛出:

  1. You did not catch the exact exception it thrown 你没有捕到它抛出的确切异常

  2. The handler rethrows the original exception 处理程序重新抛出原始异常

  3. The handler causes another exception 处理程序导致另一个异常

In your case, it hits the catch block and did not rethrow the original one, that is, it met the third circumstance: the handler causes another exception. 在你的情况下,它命中catch块并且没有重新抛出原始块,也就是说,它遇到了第三种情况:处理程序导致另一个异常。

If you can address the problem causes the exception and avoid it , then don't design it in this way. 如果你可以解决问题导致异常并避免它,那么不要以这种方式设计它。

Mr. Lippert wrote a good article about the exceptions, you might want to have a look at: Lippert先生写了一篇关于异常的好文章,你可能想看看:

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

Most probable reason is that cpusage is null or empty or without . 最可能的原因是cpusage为空或空或没有 . So when you get exception and try to use same variable again, you get the second exception. 因此,当您获得异常并尝试再次使用相同的变量时,您将获得第二个异常。

Check cpusage before using it and don't use catch the way you are using. 使用前请检查cpusage ,不要按照使用方式使用catch

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM