十大靠谱网赌平台-十大赌博平台排行榜

十大靠谱网赌平台-十大赌博平台排行榜

例外中的例外 .净

表的内容

介绍

在某一时刻,我学会了c#中的异常(我非常喜欢它),随后,在整个c#中 .净,可以有不同的行为. 更奇怪的是:并非所有的例外, 而不是总是, 可以处理和拦截吗, 这似乎完全违背了 试一试 - 抓-最后 模式.

在钻研这个的时候, 我一直在寻找越来越多的例外,这些例外实际上“打败”了 试一试 - 抓-最后 模式. 当我的清单增加到七件的时候, 我突然意识到没有任何地方可以同时找到他们, 因为任何现有的条款最多只接受两到三种情况.

这就是为什么我最终定下心来写这篇博客.

在理论上

适用性的限制

在讨论异常及其处理之前 试一试 - 抓-最后,让十大靠谱网赌平台概述这些场景可能适用的范围.

第一种情况非常明显,当您想要处理异常并提供 试一试 - 抓-最后 建设手动.

试一试
{
	/ /在这里工作
}
 (异常)
{
  / /异常处理
}
最后
{
  //一些十大靠谱网赌平台希望永远被完成的工作
}

第二种情况是当你使用的表达式,在编译时,展开成 终于尝试, i.e.,它们本质上是句法糖. 为 .净,这些都是 使用, 为each:

使用 (var resourseWorker =  ResourseWorker ())
{
  //有些人使用一次性物品
}
 (x)
{
  / /你的代码...
} 
为each (var 元素 in enumerableCollection)
{
  / /你的代码...
}

类似的结构 试一试 - 抓-最后:

var resourseWorker =  ResourseWorker ();
试一试 {
  //有些人使用一次性物品
}
最后 {
  ((IDisposable) resourseWorker).处理();
}
保龄球 __锁WasTaken = ;
试一试 {
  系统.线程.监控.输入(x, 裁判 __锁WasTaken);
  / /你的代码...
}
最后 {
    if (__锁WasTaken)系统.线程.监控.退出(x);
}
var 枚举器= enumearbleCollection.GetEnumerator ();
试一试 {
   (枚举器.MoveNext ()) {
    var 元素=枚举器.当前的;
    / /你的代码...
  }
}
最后 {
  //如果需要,处理枚举器
}

第三种情况是,当您利用可以在代码中使用上述任何表达式的库和框架时. 因此, this makes it almost impossible to find an application 为 哪一个 this would not be relevant; it means you always have protected 块s, 哪一个, 傲慢地, 总是得到执行.

然而,首先,十大靠谱网赌平台应该强调 trу-抓-最后 表情是一种非常稳定的表情. 下面是一些例子,展示了它是如何正确工作的.

对象抛出异常

试一试
{
    异常(“异常的尝试!");
}
 (异常)
{
    异常(“异常捕获!");
}
最后
{
  控制台.WriteLine (“是的! 它将被执行并记录”);
}

这是你们大多数人可能已经遇到过的情况. 然而,根据我的调查统计,有些人相信 最后 这里的街区可能过不去. 尽管如此,在这个示例代码中十大靠谱网赌平台可以看到, 最后 在应用程序的运行被中断的时候和在哪个块中被执行.

绕过 最后转到

var counter = 0;
开始Label:
控制台.WriteLine (“开始\ n”);
试一试
{
  if (计数器+ + = = 0)
  {
    控制台.WriteLine (“试一试:1 \ n”);
    转到 开始Label;
  }
  控制台.WriteLine (“试一试:2 \ n”);
  转到 EndLabel;
}
最后
{
  控制台.WriteLine (“终于\ n”);
}
控制台.WriteLine (“结束:1”);
EndLabel:
控制台.WriteLine (“结束:2”);

控制台输出

开始

试:1

最后

开始

试一试:2

最后

结束:2

直观上,人们会假设,通过使用 转到 接线生,你要绕过 最后 块; 然而, as you can see, it is still running. 这是因为触发器,用它 .净使其执行:正如微软的文档所说,当control离开试一试语句时,最后块的语句总是执行'. 只要 转到 使执行区域离开 试一试 块, 最后 一个是运行. 另一件不那么明显的事是:即使是万一 转到 向上发送控件, 最后 will still get executed; That is why, in our example, it was executed even twice.

删除带有 线程.中止

无效 线程Logic()
{
  试一试
  {
    任务.延迟(10000).Wait ();
  }
   (线程中止异常)
  {
    控制台.WriteLine (“抓:是的! 它会被记录在案的。”);
  }
  最后
  {
    控制台.WriteLine (“终于:是的! 它会被记录在案的。”);
  }
  控制台.WriteLine (“结束:不! 它不会被记录在案。”);
}
var 线程=  线程(线程Logic);
线程.开始();
任务.延迟(150).Wait ();
线程.中止 (); 

在这里,一切都很明显 中止 方法不会完全消除线程,但只会导致抛出 线程中止异常,因此,这对 试一试 - 抓-最后 表达式.

十大靠谱网赌平台还应该记住,这种方法既不可靠,也很危险. 第一个, 没有人能告诉您需要多长时间才能中断线程,甚至它是否会被中断. 第二个, 您不知道被中断的工作有多重要,也不知道它是否会损害其他线程或整个应用程序. 然而,这一点在微软的声明中得到了很好的解释 文档,很久以前.

得到一个 异常 不是继承自 系统.异常 class

基本上,这似乎与 异常类描述,根据 系统.异常 基类是否适用于所有异常. 这是真的,但只适用于内部的所有例外情况 .。净,而仍然可以从非。净获得异常.。净代码,如果您使用基于其他语言的库, 或者使用其他语言的片段.

实际上, 试一试 - 抓 只要使用,也可以捕获这样的异常吗 不指定类. 这被称为通用捕获,它可以拦截任何可能的错误.

最有趣的部分:为什么可以 试一试 - 抓-最后 失败?

杀死一个过程

很明显,如果杀死进程,两者都不会发生 也不 最后 将会执行. 另一方面,十大靠谱网赌平台必须立即提出两个问题:

  1. 这种情况多久发生一次?
  2. 十大靠谱网赌平台可以无视它,遵循“没有过程,没有问题”的原则吗?

第一个常见的例子是微十大靠谱网赌平台体系结构. 十大靠谱网赌平台器越多, 他们中任何一个人因为任何原因倒下的几率就越大, 然后, 果然, 它的所有进程都将被杀死. 现在, 当码头工人和集装箱越来越受欢迎, 应用程序体系结构几乎总是包含两个部分, 甚至有几十个, 各种microservices, 这是一个相当现实的场景.

然后,十大靠谱网赌平台也有移动应用程序. 作为一个打电话的设备,手机在任何情况下都能正常工作是至关重要的, 所以操作系统总是保留杀死任何进程的权利,一旦它感觉它的资源耗尽.

这两种情况都会导致应用程序进程的终止, 与in 哪一个 a 试一试 块 might have been executed; subsequently, 适当的 最后 块也不会运行.

现在,让十大靠谱网赌平台进入第二个问题. 如果没有流程, 假定没有问题, 因为没有人关心是否有代码在一个已经被杀死的进程中运行. 事实上,你应该关心. 在微十大靠谱网赌平台体系结构中,一个 最后 B锁可以容纳一些微十大靠谱网赌平台交互, 例如关闭事务或连接, 或者从队列中取出或放入某物. 甚至还有一件更琐碎的事情:你可能已经预料到了, 如果操作失败, 过程将会遇到 并记录下来.

上述行为与开发人员的直觉期望相反:内部代码 最后 应该被执行,那么 分组代码,以防 试一试 逻辑失败. 不过,这种行为与文档相当一致,如 B锁在异常发生时被执行. 不一定是a .网络异常, but it must be recognized by Windows' Structured 异常 H和ling (SEH); at the same time, 当进程被终止时, 不会抛出异常. 至于 最后,文档中说,一旦十大靠谱网赌平台通过 试一试 块; when a process is killed, 然而, there is just not enough time to get through at all.

现在让十大靠谱网赌平台来看一个不那么明显的例子.

FailFast & 退出

.净的 环境.FailFast 方法,该方法在被调用时将事件记录到Windows日志 ExecutionEngine异常 然后立即终止调用它的进程. 这自然会导致 试一试 - 抓-最后 这里的表达完全没有效率.

足够奇怪的是, ExecutionEngine异常 是没有任何特殊属性的普通例外吗, 也就是说它的处理方式和其他的一样.

另一个静态环境类方法是 环境.退出 that also kills the process 与in 哪一个 it is called; 作为一个结果, the 最后 B锁不会被触发. 这有点不太明显, 自, 正式, 退出方法通知应用程序完成, 与一些代码, 甚至可能成功. 然而,表达式仍然不能处理它.

损坏状态异常

损坏状态异常, 或CSE, belongs to a class that is a part of SEH; consequently, CLR和你正在开发的应用程序应该知道这个异常什么时候发生. 然而,尽管如此,它并没有被拦截或处理 试一试 - 抓-最后.

不处理此异常是微软的一个深思熟虑的决定 .净4.0的出现是因为CSE的本质.

顾名思义, 此异常是由于应用程序的已损坏状态而发生的, 即, 由于已损坏的应用程序内存, 要么在堆上,要么在堆栈上. 这意味着你完全不知道在它继续工作的情况下应用程序将如何运行. 这就是为什么微软得出结论,直接关闭应用程序更安全,而不尝试处理任何东西.

内存损坏最常见的原因如下:

  1. 轻率地使用不安全的代码.
  2. 当处理一个进程时,Windows出了问题.
  3. .净发动机故障.

然而,即使这个异常没有被处理,十大靠谱网赌平台仍然可以知道它发生了. 在终止一个进程之前, .净总是在Windows事件查看器中记录一个条目,并将应用程序状态转储到日志中. 在那里, 人们总能找到发生了什么事的信息, 和, 以防这个问题不是那么重要, 甚至可以从抛出异常的位置恢复应用程序.

你甚至可以拦截这个异常,尽管Windows会警告你,通过使用[H和leProcessCorruptedStateExcepionsAttribute], 哪个与方法有关, 使试一试 - 抓-最后表达式实际捕获损坏状态异常.

除了, 您可以将此逻辑应用于整个应用程序, 如果是需要, through adding the <legacyCorruptedState异常sPolicy> 元素 to the configuration. 然而,这只适用于 .微软网络框架, .净 Core无法捕获已损坏的状态异常, 作为一个结果, 将忽略它, 即使形式上具有上述属性.

如上所述, 已损坏的状态异常不是特定异常, 而是一整类的人. 如果你学习 .净源,你会发现有八种类型 IsProcessCorruptedState异常 方法:

  1. STATUS_ACCESS_VIOLATION
  2. STATUS_STACK_OVERFLOW
  3. EXCEPTION_ILLEGAL_INSTRUCTION
  4. EXCEPTION_IN_PAGE_ERROR
  5. EXCEPTION_INVALID_DISPOSITION
  6. EXCEPTION_NONCONTINUABLE_EXCEPTION
  7. EXCEPTION_PRIV_INSTRUCTION
  8. STATUS_UNWIND_CONSOLIDATE

InvalidProgram异常

当CLR无法读取和解释中间字节码时,将引发此异常. MSDN说, 得到这个异常通常意味着编译器中有一个错误 生成了导致错误的代码.

还有另一种方法可以获得此异常,即通过动态代码生成 ILGenerator. 因为中间代码是动态创建的, 它可能是无效的, 所以尝试执行它也会导致 InvalidProgram异常.

AppDomain & 第一个Chance异常

你们可能知道, .净具有全局的 AppDomain object; apart from that, one can leverage a number of subscriptions to various events. 十大靠谱网赌平台的特殊案例将十大靠谱网赌平台引向与异常相关的订阅,它有两个:

  1. 第一个Chance异常,当第一次向应用程序抛出任何异常时触发,并且.
  2. Unh和led异常 当任何异常被抛出时,它就会被激活,但不会被捕获.

现在让十大靠谱网赌平台看看是怎么回事 第一个Chance异常 作品. 当抛出异常时, .净运行针对该事件的所有订阅, 只有这样,应用程序才能决定如何处理异常, i.e. 哪一个 最后 块应该被执行, 从那一刻起,应用程序应该继续执行, 是否拦截异常. 随后,如果在任何订阅方法中发生了一个异常,而它没有被捕获, .净将永远不会返回来处理最初的异常, 并且应用程序将不会将控制权转移到 最后 块:

AppDomain.CurrentDomain.第一个Chance异常 += (sender, eventArgs) =>
{
  控制台.WriteLine (“美元从第一个Chance异常日志: {eventArgs.异常.信息}\n");
  if (eventArgs.异常.消息 != “从第一个Chance异常例外!")
      异常(“从第一个Chance异常例外!");
};

在这个代码示例中, 扔ing an exception is under a condition; otherwise, 这将导致永恒的递归, 自 第一个Chance异常 也对自身的异常作出响应.

AppDomain.CurrentDomain.第一个Chance异常 += (sender, eventArgs) =>
{
  控制台.WriteLine ("记录第一个Chance异常: " + eventArgs.异常.消息);
    异常(“从第一个Chance异常例外”);
};

因此,使用的事实 第一个Chance异常 是极其危险的, 因为任何内部异常都会导致整个进程被立即杀死. 但是,有一种方法可以部分地绕过它:将所有方法逻辑封装为 试一试 布洛克:

AppDomain.CurrentDomain.第一个Chance异常 += (sender, eventArgs) =>
{
  试一试
  {
    控制台.WriteLine (“美元从第一个Chance异常日志: {eventArgs.异常.信息}\n");
    if (eventArgs.异常.消息 != “从第一个Chance异常例外!")
        异常(“从第一个Chance异常例外!");
  }
   { / * * /忽略 }
}; 

你仍然要记住,这并不意味着永远不会有递归:

AppDomain.CurrentDomain.第一个Chance异常 += (sender, eventArgs) =>
{
	试一试
  {
    控制台.WriteLine ("记录第一个Chance异常: " + eventArgs.异常.消息);
      异常(“从第一个Chance异常例外”);
  }
   { / * * /忽略 }
}; 

底线:永远不要使用这个订阅来实现业务逻辑. 然而,如果它是那么危险,为什么人们会需要它呢? 例如,在记录和收集异常统计信息时,它可能会派上用场. 不过, 存在日志不可用的情况, 任何日志记录事件也会触发异常. 因此,您可能只希望在生产环境之外使用它.

Unh和led异常, 第二个与异常相关的订阅, is, 相反, 完全安全,不会干扰应用程序的执行. 使用此订阅,事件将在之后调用 .净已经完全处理了这个异常,并确保没有任何东西处理它,最终所有的块都会被执行.

最后, 一个有趣的事实:两个订阅都没有被损坏的状态异常(CSEs)触发。.

OutOfMemory异常

OutOfMemory异常 就行为而言,这与其他所有的例外没有什么不同吗.

让十大靠谱网赌平台来看一个特殊的例子:假设十大靠谱网赌平台有一个 最后 or 阻塞运行,然后由于某些原因失败. 一般, 对于开发人员, 这种行为并不比完全不运行这些块更好, 哪一种情况是可能的,当一个块开始执行时,你会得到一个异常. 另一方面,这背后的逻辑 最后 B锁通常是非常简约和可靠的,因为它的核心任务是始终保持真实. 然后, 十大靠谱网赌平台有另一个问题:十大靠谱网赌平台能在一个代码没有错误的情况下在一个块中得到一个异常吗?

要回答这个问题,你需要了解如何去做 OutOfMemory异常 作品. 作为一个规则, 十大靠谱网赌平台到达一个试一试块并分配了大量的内存, 什么导致抛出异常并成功处理.

但是,如果十大靠谱网赌平台分配了接近临界量的内存,在十大靠谱网赌平台实际到达 试一试 块,然后分配更多的内存以引起异常?

[] array1 =  [200_000_000];
[] [] array2 =  [1000][];
[] array3;
int i = 0;
试一试
{
  控制台.WriteLine (“试试:是的! 它会被记录在案的。”);
   (; i [100_000];
  控制台.WriteLine (“试试:不! 它不会被记录在案");
}
 (异常e)
{
  控制台.WriteLine (“抓,我=美元 {i}:是的! 它将被记录,但是“i”的值总是在320到380之间不同。);
}
最后
{
  array3 =  [500_000];
  控制台.WriteLine (“终于:不! 它不会被记录在案");
} 

此代码将导致 最后 块运行,但不执行,因为它只是没有足够的内存. 因此 最后 B锁将抛出一个异常, 尽管块中的代码没有包含任何问题,而且看起来相当安全可靠.

如控制台输出所示, 当第一次抛出OutOfMemory异常时,计数器变量的值总是不同的. 这是因为这个例外是不可预测的:人们无法提前知道什么时候内存不足, 因为它取决于很多因素, 例如操作系统, 内部 .净引擎,以及垃圾收集器.

让十大靠谱网赌平台还指出您可以使用多少内存来避免获取 OutOfMemory异常.

最大对象大小:

  • .净框架:2 gb. 如果您试图创建一个更大的对象, you will 得到一个例外; 然而, you can reconfigure this in the <gcAllowVeryLargeObjects> file.
  • .净 Core:在对象大小方面没有限制.

分配的最大虚拟内存量:

  • 32位进程和32位系统- 2GB,
  • 32位进程和64位系统- 4GB,
  • 64位进程和64位系统- 8TB.

在上面的例子中, we had to compile the application as a 32 bit one in order to stabilize getting the exception; otherwise, 分配的最大内存量将达到8TB.

StackOverflow异常

这里首先想到的是,十大靠谱网赌平台可以重复之前的想法 OutOfMemory异常:几乎完全填满堆栈, 进入试块, 得到一个例外, 在最后块结束时,堆栈几乎完全满了, 然后再次得到异常.

事实上,这是行不通的 StackOverflow异常 不能被拦截 试一试 - 抓-最后 表达式的开始 .净框架2.0.

如果你足够认真地阅读,你就会注意到, StackOverflow异常 是否与腐败状态例外具有相同的性质. 如果真的是这样,那十大靠谱网赌平台为什么要特别提到它呢?

但是,十大靠谱网赌平台应该这样做,因为它的行为方式与其他CSEs完全不同. 第一个区别是,从版本2开始,不再支持它的处理, 不是版本4. 第二,你不能用任何属性改变这种行为,因此, StackOverflow异常 不拦截.

嗯,正式地说,不像“永不”,因为有黑客,如主机 .净,或在堆栈溢出的情况下重写该行为. 然而,本文针对的是能够做到这一点的特定情况 突然 发生在 任何 申请,所以没有必要考虑这种奇异的选择.

So, 众所周知,堆栈溢出最常见的根本原因是冗余的方法嵌套或递归. 因此, 避免此异常最明显的方法是减少方法嵌套或使用允许将递归扩展为循环的技巧.

但是,应该记住还有另一个原因导致这个异常. 十大靠谱网赌平台都知道, 任何垃圾收集器语言的性能都有一个核心弱点:垃圾收集器本身. 因此, 如果你在堆栈上分配内存, 而不是在堆上, 当可适用, 您将使收集器更容易完成其任务并提高性能. 例如,您可以使用Span和在堆栈上分配数组 stackalloc. 另一方面, 滥用这种技术或分配太大的数组也会导致堆栈溢出异常, 哪一个, 你们可能还记得, 不妥协,不能以任何方式被拦截.

Span<int> stackSpan1 = stackalloc int[150000];
Span<int> stackSpan2 = stackalloc int[150000];
Span<int> stackSpan3 = stackalloc int[150000]; //这里我得到了OutOfMemory异常 
Span<int> stackSpan4 = stackalloc int[150000]; 

然而,这并不意味着十大靠谱网赌平台完全不应该使用这种技术. 十大靠谱网赌平台实际上可以这样做,例如 RuntimeHelper,即以下两种方法:

  1. EnsureSufficientExecutionStack 它检查堆栈上是否有足够的空间来执行一个平均值 .网络功能. 如果不是,则抛出InsufficientExecutionStack异常.
  2. TryEnsureSufficientExecutionStack, 与前一种方法相似, 它返回一个布尔值:堆栈上是否有任何空间.

您可能会认为,对于一篇技术文章来说,为一个普通函数提供足够的堆栈空间听起来相当不合适, 和, 如果你有, 你是正确的. 这是, 然而, 正如MSDN文档所说的那样, 没有指定任何确切的内存数量. 也有 一篇文章 .净特殊例外 有一些数字和解释,虽然没有任何参考资料. 请注意,我没有检查这个信息,也没有在官方文件中找到任何证据. 不管怎样,数据如下.

  • .净框架:50%的堆栈大小
    • x86: 512 KB
    • x64: 2 MB
  • .净 Core: 64/128 KB

十大靠谱网赌平台可以看到, .净 Core不那么容易恐慌,并且会在很久以后通知十大靠谱网赌平台堆栈即将耗尽, 它允许您以一种更完整、更有效的方式管理堆栈内存.

保龄球 isStackOk = RuntimeHelpers.TryEnsureSufficientExecutionStack ();
Span<int> stackSpan = isStackOk ? stackalloc int[10000] :  int[10000]; 

例如,记住这一点,只有在您确实负担得起的情况下,才可以分配堆栈内存.

结论

大多数人都会失望 试一试 - 抓-最后 因为它们误解了它们的触发规则.

开发人员会期待这一点, 如果应用程序失败, 在大多数情况下,抓块将被执行, 而 最后 总是会被处决吗. 事实上,十大靠谱网赌平台可以看到, 仅在抛出异常的情况下执行,而 最后 一旦 .。净执行区域离开 试一试 - 抓 阻塞,并且仅在CLR处于良好健康状态的情况下.

然而,是否应该在例外中避免例外的问题仍然存在. 如果你问我, 我想说,提前想太多是没有什么意义的, 因为十大靠谱网赌平台上面描述的所有情况都是非常罕见和奇异的. 更明智的做法是记住游戏规则可能会改变, 即使是语言中最稳定和可靠的表达也可能失败. 我在商业领域做了6年的开发人员, 而且只遇到过一次这样的问题. 然而, 因为我知道到底发生了什么,为什么, 我成功地节省了本来要花在调试上的许多时间. 现在,我真的希望我的研究也会对你有用.

对于上述问题,还有另一个答案, 这与微十大靠谱网赌平台和系统容错优于任何单个组件的体系结构设计原则有什么关系. 然而,这是一个完全不同的故事.

你可能也喜欢

博客文章 基于表达式树的业务规则编译器
2022年2月09年,
在这篇文章中, 我将告诉您十大靠谱网赌平台如何创建用户通知特性,以及十大靠谱网赌平台如何最终构建了一个基于表达式树的编译器,帮助十大靠谱网赌平台成功地完成了这项任务.
博客文章 具有示例的可访问组件设计
2021年12月13日
关于ARIA属性、焦点顺序等的设计器指南. 如果您设计新的组件,这些信息将派上用场, 测试接口, 或者和前端工程师一起工作.
博客文章 开发SQL查询测试系统. 第2部分
2021年10月21日
十大靠谱网赌平台开发了一个数据层测试框架,以自动化和简化在大型项目上测试复杂SQL查询的过程. 以下是对结果和变化的简短总结.