“抛出新的......”未处理的例外情况,最佳做法是什么?它已经处理完毕了

时间:2011-09-14 07:49:21

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

我尝试设置一个异常逻辑,系统的一部分可以回退到意外的行为。

应该继承一个新类,该类继承Exception对象并使用新的“exit”扩展功能,该“exit”包含对用户的错误信号和日志记录例程。

我可能需要更好地理解throw的用法,但我可以通过这样做来使其相当透明:

public SomeObject GetVersion(byte p)
{
    switch ((SomeObject)p)
    {
        case Version.SomeType1:
            ...
            break;
        case Version.SomeType2:
            ...
            break;
        default:
            throw new UnexpectedQueryException(this.someOtherObject, errorCode);
    }
    return (SomeObject)p;
}

我想你可以看到我在这里要做的事情。

当应用程序无法提供请求时,我尝试抛出。 throw用于通过异常执行执行(为调用者生成足够的错误代码)。此示例是“我知道你给了我9但这里只允许1-8”的类型错误,“errorCode进一步发送到UnexpectedQueryException(...)

不幸的是,应用程序将throw作为未处理并关闭我的线程,并且应用程序在重新启动之前将无法运行。除了这种情况,我还会使用这个抛出语句。

在我看来,这是非常有效的。

这里有什么最佳做法?
我希望异常处理能够在不同场景(如上所述)上“回退”,因此我总是有一种简单的方法将错误传达给用户(这意味着我可以发送有关异常位置的非常准确的信息) )。

此外,我当然希望应用程序继续工作。

来自异常逻辑的部分代码,

public class UnexpectedQueryException: CommunicationException
{
    public UnexpectedQueryException(SomeObject object, ErrorCode errorCode) : base("UnexpectedQueryException", object, errorCode)
    {
     .........
    }
}

反过来,它继承了基本的Exception对象,

public class CommunicationException : Exception
{
    ..some fields..

    public CommunicationException(string Message, SomeObject object, ErrorCode errorcode)
    {
     .....
    }
    public CommunicationException() : base("CommunicationException")
    { }
}

4 个答案:

答案 0 :(得分:6)

如果你在代码中抛出一个异常,你需要抓住它并用它做某事 - 如果你没有,你有处理它。< / p>

如果你扔在catch区块内,同样适用。你抛出了一个异常,它将继续传播直到找到合适的catch块。如果不存在,则表示未处理。

您需要构建更高级别的(UI)代码,以便捕获正确类型的异常并将您想要的信息传达给用户:

try
{
  // code that can throw 
}
catch(VerySpecificException ex)
{
  // communicate to user details about VerySpecificException. 
  // possibly log.
  // Do not re-throw or throw a new excpetion as it is now handled. 
}
catch(AnotherSpecificException ex)
{
  // communicate to user details about AnotherSpecificException. 
}
catch(LessSpecificException ex)
{
  // communicate to user details about LessSpecificException. 
}
catch(EveLessSpecificException ex)
{
  // communicate to user details about EvenLessSpecificException. 
}

答案 1 :(得分:3)

您需要了解如何以及何时捕获异常。

在(工作线程)线程中抛出异常的令人讨厌的事情是任何顶级异常处理程序(例如program.cs中的try / catch)都不会捕获并记录线程中抛出的异常。因此,您应该始终在线程输入方法中使用常规try / catch,至少如果您不希望应用程序死亡。

一个非常简单的规则是,您应该只捕获可以处理的异常,以便从方法中提供预期结果。在入口点防止应用程序死亡(但有时最好让应用程序死掉)。

为了更好地理解异常,您可能需要阅读我关于例外的博客文章:http://blog.gauffin.org/tag/exceptions/

答案 2 :(得分:1)

throw不会处理错误但会引发错误。如果没有throw,则无法处理错误。

通过捕获它来处理异常。您需要在代码中的某个位置调用try - catchGetVersion(或代码中的某个位置调用调用GetVersion的代码等)。如果您未在调用层次结构中捕获UnexpectedQueryException,则表示未处理,您的应用程序将停止。

调用GetVersion不同时间(不处理异常)的示例。

List<SomeObject> GetAllVersions(byte[] bytes)
{
    var result = new List<SomeObject>();

    foreach (byte b in bytes)
    {
        result.Add(GetVersion(b));
    }

    return result;
}

现在由来处理来处理异常。您可以在循环中执行此操作,以便获得包含所有成功检索的对象的结果:

foreach (byte b in bytes)
{
    try
    {
        result.Add(GetVersion(b));
    }
    catch (UnexpectedQueryException e)
    {
        // this is where your exception handling starts
        // display an error, log the exception, ...
    }
}

或者您可以在应用程序的其他级别处理异常,例如:将对GetAllVersions的调用包装成try-catch块:

List<SomeObject> = null;
try
{
    versionList = GetAllVersions(bytes)
    // do something with versionList
}
catch (UnexpectedQueryException e)
{
    // this is where your exception handling starts
    // display an error, log the exception, ...
    // Note that versionList will be null in error case
}

这是例外的主要优点。它们在整个调用堆栈中传播。因此,您不需要在错误之后的代码行中处理它,而是在您认为合适的应用程序中的某处。

答案 3 :(得分:-3)

  

不幸的是,应用程序将throw视为未处理并关闭   我的线程和应用程序在重启之前不会运行。除此之外   我也会在catch语句中使用此方法。

您提供的代码会始终引发异常,因为您尝试将 byte 类型的值类型转换为 SomeObj 类型的引用类型:

public SomeObject GetVersion(byte p)
{
    switch ((SomeObject)p)
    {
        case Version.SomeType1:
            ...
            break;
        case Version.SomeType2:
            ...
            break;
        default:
            throw new UnexpectedQueryException(this.someOtherObject, errorCode);
    }
    return (SomeObject)p;
}