Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 未经处理的异常由一个;抛出新的..”;,什么';什么是最佳实践?它';他已经处理好了_C#_Multithreading_Exception Handling_Try Catch - Fatal编程技术网

C# 未经处理的异常由一个;抛出新的..”;,什么';什么是最佳实践?它';他已经处理好了

C# 未经处理的异常由一个;抛出新的..”;,什么';什么是最佳实践?它';他已经处理好了,c#,multithreading,exception-handling,try-catch,C#,Multithreading,Exception Handling,Try Catch,我尝试将一个异常逻辑放在系统的某个部分可以依赖于意外行为的异常逻辑上 应该对继承Exception对象的新类进行操作,并使用一个新的“exit”扩展功能,该“exit”由发送给用户的错误信号和日志例程组成 我可能需要更好地理解throw的用法,但我认为我可以通过以下方式使其相当透明: public SomeObject GetVersion(byte p) { switch ((SomeObject)p) { case Version.SomeType1:

我尝试将一个异常逻辑放在系统的某个部分可以依赖于意外行为的异常逻辑上

应该对继承
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;
}
我想你能明白我在这里想做什么

当应用程序无法满足请求时,我尝试抛出。抛出意味着让执行通过异常(这会为调用方生成足够的错误代码)。此示例是一个类型为“我知道您给了我一个9,但这里只允许1-8”的错误,errorCode会进一步发送到
意外查询异常(…)

不幸的是,应用程序将抛出视为未处理,并关闭我的线程,应用程序在重新启动之前不会运行。除了这个场景之外,我还将使用这个抛出catch语句

在我看来,这是非常容易处理的。

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

当然,我也希望应用程序继续工作

异常逻辑中的一部分代码,

public class UnexpectedQueryException: CommunicationException
{
    public UnexpectedQueryException(SomeObject object, ErrorCode errorCode) : base("UnexpectedQueryException", object, errorCode)
    {
     .........
    }
}
这反过来又继承了基本异常对象

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

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

如果您在代码中抛出异常,您需要捕获它并对其进行处理-如果您不这样做,您就没有处理它

如果在
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. 
}
不幸的是,应用程序将抛出视为未处理并关闭 我的线程和应用程序在重新启动之前不会运行。除此之外 场景我也在使用这个抛出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;
}

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

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

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

    return result;
}
在(worker)线程中抛出异常的糟糕之处在于,任何顶级异常处理程序(如program.cs中的try/catch)都不会捕获并记录线程中抛出的异常。因此,至少在不希望应用程序死机的情况下,线程入口方法中应该始终有一个通用的try/catch

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


为了更好地理解异常,您可能需要阅读我关于异常的博客文章:

A
throw
不会处理错误,但会引发错误。如果没有
抛出
,就没有要处理的错误

通过捕获异常来处理异常。在调用
GetVersion
的代码中的某个地方(或者调用调用
GetVersion
的代码中的某个地方),需要一个
try-catch
块。如果您没有捕获调用层次结构中的
意外查询异常
,则该异常未经处理,应用程序将停止

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

或者,您可以在应用程序的另一个级别处理异常,例如,将对
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
}
List=null;
尝试
{
versionList=GetAllVersions(字节)
//用版本列表做些什么
}
捕获(意外查询异常e)
{
//这就是异常处理开始的地方
//显示错误,记录异常。。。
//请注意,在错误情况下,versionList将为null
}

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

您应该发布调用
GetVersion
的代码,然后处理异常。没有任何迹象表明您已经处理了异常@丹,谢谢你。我认为这个评论需要更好的解释。当运行
抛出新的unexp..Exception()
时,如果不将执行移到其中,会发生什么?GetVersion是在try/catch块内调用的,而try/catch块的catch中又有一个
抛出新Unexp..()
。这个异常肯定不会是一个意外的QueryException“。因为您试图将byte类型的值类型转换为SomeObj类型的引用类型”--当然,这不是问题的一部分。只是一些名字的快速修改。啊!我理解。Throw用于将执行发送到最近的catch语句。如果我投下一个球,它只会绕圈子。因此,我在UnexpectedQuery()中进行了一些处理。最近的Catch子句应该做什么?(我理解它不应该抛出,在这种情况下)@Jonas-不是在圆圈中-它在堆栈中上升,而不是停留在相同的
try{}catch{}
块中。您可以在
catch
块中嵌套
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
}