• (cs)

    The real WTF is why is the coder wasting CPU cycles trying to catch exceptions here.  There is no need for the try block.  As for the ThreadAbortException, you have to do that to eat the exception automatically generated by Response.Redirect.

  • (cs)

    ROFL
    I get it! a VB 'programmer' trying to understand the try/catch construct!
    That's NEVER gonna happen! WTF!

  • (cs) in reply to DJDanny
    DJDanny:
    *ROFL*
    I get it! a VB 'programmer' trying to understand the try/catch construct!
    That's NEVER gonna happen! WTF!


    [8-)]

    I really like the empty Finally block too.
  • (unregistered)


    http://support.microsoft.com/default.aspx?scid=kb;EN-US;312063

    the boolean tells the code whether to stop the response at the point of
    redirect, or not. By default, it is true, so a ThreadAbortException (I
    believe) is thrown behind the scenes to signal to the framework to stop
    processing the last request immediately (note this is important as any
    code past that point could be run if it were set to false). For the
    default value of true, you don't notice the exception of course, unless
    you do a redirect inside of a try...catch block. Then you'd want to use
    the overloaded method passing in false for 'end response' arg.

  • (cs)

    Well, technically it's correct. Response.Redirect calls Response.End which always throws the exception. (Maybe that's the real WTF: a method that always throws an exception!) See:

    1. Response.Redirect documentation:
      http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemWebHttpResponseClassRedirectTopic1.asp?frame=true
    2. Response.End documentation:
      http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemwebhttpresponseclassendtopic.asp?frame=true

    However, it is a WTF because a better solution exists: Response.Redirect(targetUrl, false): http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemwebhttpresponseclassredirecttopic2.asp?frame=true .

    Have a nice day!

  • (cs)

    I've been curious about this before too.  In fact I've written similar code:

    [code language="c#"]try
    {
     Response.Redirect("thankyou.aspx");
    }
    catch (ThreadAbortException) { }[/code]

    I guess I was used to the way regula' old ASP did a redirect - by ending the processing of the current request.  And this is not the way the creators of ASP.NET were thinking.
    Lesson learned.

    [code language="c#"]Response.Redirect("thankyou.aspx", false);[/code]

  • (unregistered)

    Ack, the WTF in this post is the COLOR SCHEME!!!

    Another guy getting nostalgic for DOS 3.3? Or what?

  • (unregistered)

    Or maybe we can just randomly add

                System.Threading.Thread.CurrentThread.Suspend();

                System.Threading.Thread.CurrentThread.Resume();

    blocks to our code.  After all, it seems to be running too fast.<!--EndFragment-->

  • (unregistered)

    If you use the optional second parameter of the ASP.NET Response.Redirect method, the one named endResponse, the Exception will never be thrown, as the thread will not be aborted prematurely.

    http://support.microsoft.com/default.aspx?scid=kb;en-us;312629

  • (cs)

    I get it! The WTF is not in the code but in the comments...

    The first WTF comment says:

    <font color="#008000">'Do nothing as response.redirect always generate this exception</font>

    But it should say

    <font color="#008000">'Do nothing as response.redirect always generate this exception unless
    'I call the overloaded redirect with that endResponse extra parameter
    'that avoids the exception being thrown and performs better, this because
    'I'm to lazzy to read the API docs or even looking at the options that
    'intellisense brings me.</font>

    The second says

    <font color="#008000">'Propagate exception</font>

    And it should say

    <font color="#008000">'Who said I was lazy?
    'Look how I'm catching an exception here just to throw it again
    'just for the sake of doing it.</font>

    And there’s a block of code lacking of a comment that should say.

    <font color="#008000">'Maybe is just me but a try block looks faulty without the finally part.</font>

  • (cs)

    You DO NOT need to swallow ThreadAbortException. In fact, if you find yourself doing so there's probably something wrong with your code. The framework throws that to unwind your thread when it ends the request. An exception is the only way to do this cleanly. If you've got more processing going on there that has to happen after you've Response.Redirect'ed or Server.Transfer'ed you either need to move that processing somewhere else or use the optional parameter to inform the framework not to terminate processing on this thread.
    Moreover, catching ThreadAbortException WILL NOT stop it from propagating up the call stack. It's special in this regard because in general it's not supposed to be caught. The only way to "swallow" TAE is to call Thread.ResetAbort(). But again, you really ought not to be doing that anyway.
    So really, whenever I see someone trying to swallow TAE, that's a WTF to me.

  • (cs) in reply to zinglons_ale

    >It's special in this regard because in general it's not supposed to be caught.
    That really ought to read "swallowed" instead of "caught."

  • (unregistered)

    Seeing a variable declared within the TRY block (which is never used) actually reminded me of what I theorize must be the only reason for a FINALLY section to ever exist: variables declared within the TRY are still in scope.  Otherwise, what is the point of the FINALLY section?

  • (cs) in reply to

    anonymous: The point of the finally is to close any connections or files that may still be open.

    try
    {
    connection.open();
    int.parse("A");
    }
    catch{}
    finally
    {
    connection.close();
    }

  • (cs) in reply to Scott

    (sorry, Anonymous was me, I wasn't logged in)

    Yes, I understand in theory its there so you can "clean up", that's fine, but there is no difference between doing it in the finally block or doing it right after --  unless you wish to reference objects declared within the TRY that would otherwise be out of scope.

    Your example is easily written as:

    try
    {
    connection.open();
    int.parse("A");
    }
    catch{}

    connection.close();


    and does the exact same thing, since the object "connection" is still in scope after the TRY/CATCH code is completed, whether there's an exception or not.  Make sense?

  • (cs) in reply to Jeff S

    (me again)

    and actually, your example (which I ended up using) is a bad one because the finally() block might cause an error if the connection never did open successfully.  remember, finally() is executed whether or not an exception occured, not just if the TRY was successful.

  • (unregistered) in reply to Jeff S

    Except that the finally will ALWAYS execute; programmatic control may be thrown to another module/class/procedure by the exception. Not every try needs to have a local catch associated with it; the exception may be caught several layers upstream.

    (Stan Rogers, who has not yet created a local ID here.)

  • (cs) in reply to Jeff S

    @Jeff,

    In this code the connection will never be closed because when there is an exceiption within the try/catch the code stops executing at the end of the catch block, it doesn't continue on to where you are closing the connection, which is outside of the try/catch block. That's why a finally block is needed.

  • (cs) in reply to skicow

    Sh1t, disregard this, I was drunk a few minutes ago when I wrote this[:S]

  • (cs) in reply to

    Stan -- can you give an example?

  • (cs) in reply to skicow

    Well, it IS possible to create a catch that is the equivalent of On Error Resume Next, so you can't say that the close() will never be caught just because it lives lower down the page.

  • (cs) in reply to Stan Rogers

    hmmm... I think you missed the point -- it wasn't to criticize your code!  it was to indicate that what you posted in no way requires a FINALLY clause. no worries, though.

  • (cs) in reply to Jeff S

    An exception will be thrown to the lowest-flying catch that accepts its signature. If you call a method from within a try block, which in turn calls a method that has a try block, and only initial calling method has a catch that accepts an exception that's thrown in the lowest-level try block, then the exception will be caught by the calling method's catch block. That may transfer control elsewhere or halt the whole application, there's no guarantee that (in the example) close() would ever be called. If it's in a finally block, it will be called regardless of where the high-level catch sends the rest of the execution stream.

  • (cs) in reply to Stan Rogers

    A ha!  i think i got it:

            Try
                i = i / 0
            Catch ex As Exception
                MsgBox("exception is caught")
                Exit Sub
            Finally
                MsgBox("Finally")
            End Try

    The "exit sub" still executes the FINALLY block of code !  now, I get it!  I just couldn't wrap my mind around this until I considered an exception that exits the procedure or function.

    Thanks!!

  • (cs) in reply to Jeff S

    A more common situation needing finally would be:
    try
    {
        connection.open();
        // do some work using connection which could throw
        if(something == 5) return;
        // do more work
        if(somethingelse == 3) return;
        // etc.
    }
    catch(Exception ex)
    {
        // report error
    }
    finally
    {
        connection.close();
    }

    Without the finally, those test become similar to:
        if(something == 5)
        {
              connection.close();
              return;
        }

    So if you can imagine having several exit points and several connections, files, etc. that need to be cleaned up you get a lot of redundant code, and if certain items only need to be cleaned up after you've reached a certain point in the process then you either needlessly test them everywhere or risk missing necessary cleanup.

  • (cs) in reply to Scott B.

    Actually, the above should look like this so to make it programmatically correct...

    This should provide the correct functionality. And after Response.Redirect("page.aspx", true) happens, no more action is requried on your part.

    [code language="c#"]
    try
    {
       connection.Open();
       // do some work with said connection

    }
    catch
    {
    }
    finally
    {
       if(connection.ConnectionState != ConnectionState.Closed)
       {
          connection.Close();
       }
    }
    [/code]

  • (unregistered)

    You are all missing my favorite part of the code, which is the misspelt comment that says <font color="#008000">'Initialise the page </font><font color="#000000">followed by a commented out call to InitPage().  You know this whole mess of a coding exercise started with two lines of code, the call to Response.Redirect and the call to the InitPage() function and degraded once they realized that InitPage wasn't being called.  Now the function call is gone and the mess remains, oh the irony [8-)].

    bj</font>

  • (cs)

    Whoa holy crap I can't believe someone did that, what a waste of resources and it totally shows that... LOL bah screw it, I can't even pretend. I have no clue what's going on because I'm a lowly VB "programmer" (as someone so demeaningly referred to us yesterday). I can guess at what's going on though.
     
    It's like having an If structure where you put in an Else statement but don't actually have anything happen there. To compound the matter, it would be like saying "If 1 = 1", which is ALWAYS true (except for when the skies open and fire rains from the heavens and the Rapture is upon us). Am I close? Do I win a prize if I am?

  • (unregistered) in reply to Jacob K

    Even better solution is to use "using" clause (we are talking C#, aren't we?): http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/vclrfusingstatement.asp
    Connection should implement IDisposable though (which should check if it is opened and call close).

  • (unregistered) in reply to

    Hate to be the spelling police, no I don't I love it.

    Initialise is spelt correctly if your from the UK, we just have to suffer the bastardisations of the english language and colourful interpretations of the original form by Americans who changed it because it was too hard.

    [;)]

  • (unregistered) in reply to zinglons_ale

    In Tagalog, "tae" means feces. Umm. Just wanted to share... 

  • (unregistered) in reply to Jeff S

    uh oh. Jeff is a vb coder. That explains why he doesn't understand try/catch/finally.

    Personally, I think typing

    ON ERROR RESUME NEXT

    at the top of the page solves all your problems.

    vb programmers should be kept inside their own little world so that their code doesn't leak out into the real world. So that those who know what they're doing can sit back and write proper code, and those who dont can sit in their own little world writting rubbish code in vb.

  • (unregistered) in reply to

    [6]
    Condeming VB programmers is not fair!  I am a VB programmer, and I also know Assembly, Pascal, C, C++, Java, C#, and J#.  So you are saying that because I use VB to develop a program I am not skilled enough?  Well go ahead and condem all the programmers at Microsoft that developed the Office Suite.  It is written in VB[8o|]

  • (cs) in reply to

    That's a pretty bold thing to say, especially considering you didn't even have the guts to post a name!

    Yes, very clearly all I know is VB !  That is quite apparent, since I never saw the need to use a FINALL clause in my app; how can someone be a true programmer w/o ever using that feature?  it's impossible!  Any programmer who knows C or  C++ (or assembly language for that matter) clearly should know about TRY/CATCH/FINALLY from using those languages, right?

    Very, very sad!  I look forward to seeing some of your code highlighted here in the future!  Your comment about "just adding ON ERROR RESUME NEXT" to solve all the problems here is very telling, indeed!





  • (unregistered) in reply to Jeff S
    Jeff S:
    That's a pretty bold thing to say....


    For someone who refuted the usefulness of the Finally statement a few posts back, you got awfully stirred up by that lame VB insult!

    (not the same Anon as any of these other posts)     
  • (unregistered)

    Disregarding the myriad ways that one can avoid the System.threading.ThreadAbortException being thrown in the first place, the code looks to deal with it fine. Not the most graceful way of dealing with it, I grant you, but still. The other way of doing it, I guess would be:

    ...
    Catch ex as exception
    if not typeOf(ex) is System.Threading.ThreadAbortException Then Throw
    Finally
    End Try
    End Function

    This adds one more operation to the process - Catch the  error, get its type, and act accordingly, move on to the finally block.

    Doing it the way he has, has cut half of that process out - Catch the specified error and act accordingly (in this case, doing nothing) and then move on.

    I'm not saying it looks pretty, but in the circumstances, it's OK. I think.

  • (cs) in reply to

    Sorry, I did not mean to "refute the usefulness" -- I simply asked WHY is it useful, because I didn't know! and now I do!  Is that a bad thing?  I guess my mistake was to ask for some guidance on a topic I needed some clarification on.  

  • (cs) in reply to Jeff S

    @Jeff:  To add to your last comment, the finally block also executes if the exception is rethrown. 

    try
    {
    //something
    }
    catch (Exception ex)
    {
        throw ex;
    }
    finally{}

  • (cs) in reply to Scott

    Thanks, Scott !

  • (cs)

    I would have done something more like this...

    Dim responseUrl As String

    Try
       
       'Build responseUrl in try because it looks 
       'like we are calling methods that may fail
        responseUrl = "GLSCWizard_SA.aspx?stat=" & Enumerations.PageState.Add_Mode & "&seid=" & lSurveyEventID & "&said=0")

    Catch

        ex As SomeOtherExceptionBesidesSystem.Exception
        'Do something meaningfull if Try code fails
        throw

    'Redirect if no errors occured above
    Response.Redirect(responseUrl)

  • (cs) in reply to BrianScott

    I would have done something more like this...

    Dim responseUrl As String

    Try
       
       'Build responseUrl in try because it looks 
       'like we are calling methods that may fail
        responseUrl = "GLSCWizard_SA.aspx?stat=" & Enumerations.PageState.Add_Mode & "&seid=" & lSurveyEventID & "&said=0")

    'Line break above was in wrong place
    Catch ex As SomeOtherExceptionBesidesSystem.Exception
        'Do something meaningfull if Try code fails
        throw

    'Redirect if no errors occured above
    Response.Redirect(responseUrl)

  • (unregistered)

    Jeff : What about a Catch that just ReThrow the Exception... you'll also need the finally.

  • (cs)

    To be quite honest, I think the WTF is from Microsoft here. Why on Earth should moving control to a different page cause an exception???

    I suppose that if you're one of the object-obsessed, Ada-worshipping types that seem to have resulted from the object explosion of recent years, you can justify this sort of thing. But personally, if I'm moving control from one part of my application to another, I don't expect my language framework to complain!

  • (cs)

    ThreadAbortException ... [:-*]the thread is being aborted

    Better to use using for connections...


    using(SqlConnection connection = new SqlConnection())
    {



    }

  • (cs)

    [code language="c#"]


    SqlDataAdapter dsCommand = new SqlDataAdapter();
    SqlConnection connection = new SqlConnection
    (FooBarApplicationConfiguration.ConnectionString);
    try
    {
         dsCommand.SelectCommand = new SqlCommand("uspFoo", connection);
         dsCommand.SelectCommand.CommandType = CommandType.StoredProcedure;
         dsCommand.SelectCommand.Parameters.Add(new SqlParameters("@foo", SqlDbType.VarChar, 10));

         dsCommand.SelectCommand.Parameters["@foo"].Value = "blah";

         dsCommand.fill(myDataSet);

    }
    finally
    {
        if ( dsCommand != null )
        {
            if ( dsCommand.SelectCommand != null )
            {
                if ( dsCommand.SelectCommand.Connection != null )
                {
                   dsCommand.SelectCommand.Connection.Dispose(); 
                }
                dsCommand.SelectCommand.Dispose();
            }
            dsCommand.Dispose();
        }
    }






    [/code]

    Thought i would add to the flame :) This is the proper use of a try block, some may argue... some may agree.. but hey, whatever floats your boat...  if there are any exceptions thrown, they're caught at the application level and logged using my SystemFramework.ApplicationLog  and SystemFramework.ApplicationTrace objects.

    don't catch everything under the sun [:@]   i.e.  catch ( Exception ex )
    Not only is it bad practice, but the overhead.......

    Thanks! [:D]

    P.s. -- wrote this right here in the post, so if there's issues..... oh well
  • (cs) in reply to Chris Butler

    OH of course--- the class that implements this code -- implements IDisposible, and the code that calls this class includes


    using ( DataAccess.myClass myClassDataAccess = new DataAccess.myClass() ) 
    {
       // call the object i just showed you here
    }

  • (unregistered)

    DJDanNY:
    You're an ass.   There are more than enough examples of poor coding practices in all languages.  Some of the worst are in languages like C where you can do some real damage with pointers and no bounds checking. 

    The language wars are over.  Get over it. 


    Scott:
    You just need to check the state of the connection before you try to close it:

    try
    {
    connection.Open();
    int.Parse("A");
    }
    catch{}
    finally
    {
       if( connection.State = ConnectionState.Open)
         {
             connection.Close()
         }
    }

    Dave - http://www.geekswithblogs.net/dtotzke

  • (cs) in reply to

    Or... you could just dispose it ;)

  • (cs) in reply to
    :
    DJDanNY:
    You're an ass.   There are more than enough examples of poor coding practices in all languages.  Some of the worst are in languages like C where you can do some real damage with pointers and no bounds checking. 

    The language wars are over.  Get over it. 


    Scott:
    You just need to check the state of the connection before you try to close it:

    try
    {
    connection.Open();
    int.Parse("A");
    }
    catch{}
    finally
    {
       if( connection.State = ConnectionState.Open)
         {
             connection.Close()
         }
    }

    Dave - http://www.geekswithblogs.net/dtotzke


    Why have an empty catch block?  It isn't required, and won't accomplish anything.

    try
    {
    connection.Open();
    int.Parse("A");
    }
    finally
    {
       if( connection.State = ConnectionState.Open)
         {
             connection.Close()
         }
    }

  • (cs) in reply to Blue

    <font style="BACKGROUND-COLOR: #efefef">*** see code and comments above in my previous post...   [:D]

    BAD empty CATCH !! BAD!!!!!!! Makes for poor debugging..... and poor error handling... wait... "error handling"... if something does throw an error... the world may never know!!! [:O] 
    </font>

Leave a comment on “Don't worry, it always does that”

Log In or post as a guest

Replying to comment #:

« Return to Article