随笔 - 89, 评论 - 163, 引用 - 33

导航

关于

标签

每月存档

最新留言

广告

你知道吗?你可以在异常中解退调用栈

 

[原文作者]:Bill Horst

[原文链接]:Did you know? You can unwind the call stack from exceptions (Bill Horst)

    解退一个异常堆栈的能力是Visual Basic.NET 2005的一个新引进的特性。当调式器触发了一个异常,你可以解退这个堆栈以便于使用代码编辑器修复这个异常并继续调式 修改后的代码。这个异常辅助用户界面有一个“Enable Editing”选项,这个选项可以在当前Solution中展开调式器到代码堆栈的最顶端。

 

  

 

 

    当一个异常未被处理的时候,unwind将会自动发生,但是这个特性可以在Options dialog(在Tools下面)被开启或关闭。(见下图)

  

  

 

    如果你试图在一个异常被触法后去编辑代码,并在解退栈之前,你可以被允许去使用“解退栈并且编辑代码”,“终止代码调试的session”,或“取消编辑”这三个选项。(见下图)

 

    

 

      用户还可以从call stack窗口中进行解退栈,通过在需要的Call stack中单击右键并选择“Unwind To This Frame”。这个特性只是当异常已经被处发并且没有被解退栈时才有效,并且只有当在堆栈的足够靠前的的地方才有效。(见下图)

 

  

     我们希望这个特性可以给您提供更有效率的代码调试,并可以帮助您加强在Visual Basic中使用“Edit and Continue”能力。

posted on 2009-01-23 13:34:31 by vbcti  评论(1) 阅读(3059)

VB Catch …When 为什么这么特别?

 

    [原文作者]:Jared Parsons

    [原文链接]:VB Catch ... When: Why so special?

    VB Catch 的语法有一个独特的特点:When。它允许用户通过表达式筛选一些情况,而不是仅仅是筛选它的类型。 任何的代码都可以添加When去决定是否要处理某个异常。

    Sub Sub1()

    Try

    DoSomeAction()

    Catch ex As Exception When Filter(ex)

    Stop

    End Try

    End Sub

    新闻组通常会问,“为什么这么特别呢?”我也可以通过C#做同样的处理,例如:

static void Sub1()
{
    try
    {
        DoSomeAction();
    }
    catch (Exception ex)
    {
        if (Filter(ex))
        {
            throw;
        }
        HandleException();
    }
}
 
在某种程度上来说,确实是这样的。两种情况下代码都通过调用筛选程序来做决定是否要处理这个异常。细微的不同是在调用筛选的时候。
 
在VB中,When语句是作为IL异常来执行的。当异常被抛出,异常的筛选程序在堆栈展开之前就在进行了。这表示如果筛选方法创建了包括当时的堆栈的错误报告,它就可以展示出异常在什么地方发生的。
 
例如,在上面的代码中,如果DoSomeAction()被抛出,堆栈在筛选程序的表达式里面被检查,下面的堆栈就会被展示出来。
 
 
                
 
 注意,怎么使得DosomeAction这个方法如此清晰可见的?这对错误报告和调查都是很有力的帮助。它也允许在真正出错的语句上设置断点,而不仅仅只是一个验尸报告。
 
 在C#里面执行的代码是发生在堆栈展开之后。只要你不是在执行最优化的代码,仍然可以通过堆栈得到异常的原代码。但是你就不能在错误出现时检查代码了。
 
 
 
                
 
 
 

posted on 2009-01-23 11:23:39 by vbcti  评论(0) 阅读(3067)

什么时候可以捕捉到StackOverflowException(堆栈溢出)异常?

[原文作者]Mary Lee
       答案是:当你抛出它的时候
       从CLR 2.0开始,触发StackOverflowException异常的条件就改变了,用户不能触发这个异常(备注1),如果发生异常的话取而代之的是CLR会直接结束掉发生异常的进程。
但是事实并不是100%如此,用户代码仍然能够人为抛出StackOverflowException异常,当然不是通过真正的溢出错误,而是用户手动调用。这和文档上说得不一样,这里我们用一个不太规范但是很简单的程序来说明这种情况。(见备注)
      当然,这种用法没什么特别的,但是我还是觉得有必要提到这点,因为最近我看了一个新讨论组的谈话记录,有人发布了些简单的异常触发代码,碰巧里面提到StackOverflowException。他的代码里直接抛出了这个异常,而且他也有足够的理由相信这个异常在产品代码中也可以被抛出,对此我真的感到非常惊讶。
      请不要认为这篇文章提倡用户来抛出StackOverflowException异常(你当然不应该这么做),所有介绍都只是我的一点兴趣。坦白说我希望任何情形这个异常都是不能被捕捉的。
      public static void CatchStackOverflow1() {
    try {
        throw new StackOverflowException();
    } catch (StackOverflowException ex) {
        // Executes and handles the exception.  User code continues
        Console.WriteLine(ex.Message);
    }
   }
 
   static int CreateRealOverflow(int p1) {
    return 42 + CreateRealOverflow(p1 + 1);
    }
 
   public static void CatchStackOverflow2() {
    try {
        CreateRealOverflow(42);
    } catch (StackOverflowException ex) {
        // Will not execute
        Console.WriteLine(ex.Message);
    }
   }
 
   static void Main(string[] args) {
    CatchStackOverflow1();
    CatchStackOverflow2();
  
}
      [1]除非你可以在CLR托管的情况下执行一些回收机制,这当然是一个例外而不是规则规定的
 
 

posted on 2008-11-28 09:42:11 by VBCTI  评论(0) 阅读(6574)

正确操作windows窗体的Timer事件

[原文作者]Jared Parsons                                       
 
     Windows窗体的时间(Timer)类允许用户在一个时间段内执行特定的操作。时间对象会在设定的时间内开始一个Tick事件,用户可以容易的响应这个事件。如果软件开发者想在在一个指定的时间段内检查一个特定的条件(比如2秒钟,我会在这篇文章中用两秒作为范例),这时这个事件就会非常有用。
 
     偶尔用户会惊奇的发现Tick事件会比期望当中的更快地被触发。比较在两个调用期间等待两秒钟而言,取而代之的是Tick事件几乎是在一个被调用的过程完成后就被立即被触发了。
 
     这里所发生的是这个事件在事件循环机制作用下所产生的状态变化。时间事件的间隔期是由现实世界的时间来计算的。所以直白的讲,每隔两秒钟windows将认为时间间隔结束,然后发送一个新的Tick事件消息。下一时间段的windows窗体事件就不会再执行代码,一个tick事件会被触发【1】。
 
     现在我们可以想象一下我们已经有如下的代码。
 
     Private Sub OnTimerTick () Handles m_timer.Tick
         RunSomeOperation ()
     End Sub
 
     考虑一下如果 RunSomeOperation 用时超过2秒钟将发生什么。Tick事件会在RunSomeOperation过程当中被实时的触发,另外一个Tick事件会等候处理。一旦我们离开OnTimerTick过程,我们会回到Windows窗体代码,这些代码会巡视到Tick事件并且促使触发它,让我们重新回到OnTimerTick过程。
 
     这是与大多数人的期望矛盾的。大多数人会期望Tick事件应该在窗体代码完成后的两秒被触发。
 
     要想解决这个矛盾,开发者可以在处理一个timer事件的时候停止时间计数器的计数。然后再退出事件处理程序后从新激活计数器。这会使windows从激活计数器时才开始计算时间间隔。这样做的结果是使得timer事件在代码停止执行后的两秒钟才被触发。请参考以下代码:
 
    Private Sub OnTimerTick () Handles m_timer.Tick
      M_timer.stop ()
      Try
             RunSomeOperation ()
       Finally
             M_timer.Start ()
       End Try
    End Sub
 
 
 
      【1】这不是100%正确。不过这确实是无论什么时候应用程序开始又一次的循环事件时的情况。循环事件(更加确切的说是当循环事件发生或没有发生的时候)也与我们的这篇讨论相关联。

posted on 2008-11-07 14:35:41 by VBCTI  评论(0) 阅读(3100)

Powered by: Joycode.MVC引擎 0.5.2.0