none
Loop Computation Time Increases Dramatically With Small Change RRS feed

  • Question

  • I recently made a change to the code within a loop in my code, and now when I run the code through Visual Studio 2010 Express, the loop runs about 10x slower than the previous loop.  I did not make any significant changes (to my knowledge) to the code within the loop.  I made the change so that the loop could handle various conditions I imposed in another section of the code.  I know that it is this loop that is slowing everything down because I report the loop progress on my form.  This version of the code runs fast:

    For k = 0 To MCPoints Phi = k * PhiStep TotalForce = AppliedForce + 100 * AcceptableDiff Upper = LS_Compression Lower = -LS_Tension + Phi * (CLSLoc - TLSLoc) Cpoint = (Upper + Lower) / 2 Dim LoopCounter As Integer = 0 While Abs(TotalForce - AppliedForce) > AcceptableDiff Dim Strain As Double = 0 Dim Stress As Double = 0 Dim ForceC As Double = 0 Dim MomentC As Double = 0 Dim ForceS As Double = 0 Dim MomentS As Double = 0 Dim ForceRem As Double = 0 Dim MomentRem As Double = 0 Dim StrainMod As Double = 1 Dim Factor As Double = 1 Dim StrainAtOuterSteel As Double = 0 If FactorValues = 1 Then StrainAtOuterSteel = (Cpoint + Phi * (ColHeight - CLSLoc)) - Phi * (ColHeight - LocOuterSteel) If StrainAtOuterSteel >= -0.002 Then Factor = 0.65 ElseIf StrainAtOuterSteel < -0.002 And StrainAtOuterSteel > -0.005 Then Factor = 0.65 + (Abs(StrainAtOuterSteel) - 0.002) * (250 / 3) Else Factor = 0.9 End If End If For j = 0 To MCGrid.GetLength(1) - 1 Strain = (Cpoint + Phi * (ColHeight - CLSLoc)) - Phi * (ColHeight - MCGrid(4, j)) MCGrid(9, j) = Strain If MCGrid(8, j) = 1 Then Stress = UnconfinedConcrete(Strain) MCGrid(10, j) = Stress ElseIf MCGrid(8, j) = 2 Then If TreatAsUnconf = 0 Then Stress = ConfinedConcrete(Strain) Else Stress = UnconfinedConcrete(Strain) End If MCGrid(10, j) = Stress End If MCGrid(11, j) = MCGrid(10, j) * MCGrid(5, j) 'Force MCGrid(12, j) = MCGrid(11, j) * MCGrid(7, j) 'Moment ForceC = ForceC + MCGrid(11, j) MomentC = MomentC + MCGrid(12, j) Next For j = 0 To MCReinf.GetLength(1) - 1 Strain = Round((Cpoint + Phi * (ColHeight - CLSLoc)) - Phi * (ColHeight - MCReinf(1, j)), 6) MCReinf(5, j) = Strain If S_SteelModel = 1 Then If Strain < 0 Then StrainMod = -1 Else StrainMod = 1 End If MCReinf(6, j) = StrainHardeningSteel(Strain * StrainMod) * StrainMod ElseIf S_SteelModel = 2 Then If Strain < 0 Then StrainMod = -1 Else StrainMod = 1 End If MCReinf(6, j) = MenegottoPinto(Strain * StrainMod) * StrainMod End If MCReinf(7, j) = MCReinf(6, j) * MCReinf(4, j) ForceS = ForceS + MCReinf(7, j) MCReinf(8, j) = MCReinf(7, j) * (MCReinf(1, j) - ColHeight / 2) MomentS = MomentS + MCReinf(8, j) If TreatAsUnconf = 0 Then ForceRem = ForceRem + MCReinf(4, j) * ConfinedConcrete(Strain) MomentRem = MomentRem + MCReinf(4, j) * ConfinedConcrete(Strain) * (MCReinf(1, j) - ColHeight / 2) Else ForceRem = ForceRem + MCReinf(4, j) * UnconfinedConcrete(Strain) MomentRem = MomentRem + MCReinf(4, j) * UnconfinedConcrete(Strain) * (MCReinf(1, j) - ColHeight / 2) End If Next TotalForce = ForceC + ForceS - ForceRem TotalMoment = MomentC + MomentS - MomentRem If TotalForce > AppliedForce Then 'If (Cpoint + Phi * (ColHeight - CLSLoc)) - Phi * (ColHeight - TLSLoc) < -LS_Tension Then 'Lower = Cpoint 'Else 'Upper = Cpoint 'End If Upper = Cpoint Cpoint = (Lower + Upper) / 2 Else Lower = Cpoint Cpoint = (Lower + Upper) / 2 End If If LoopCounter > MaxIterations Then ConvFailure = 1 'MsgBox("k = " + CStr(k) + " Force C = " + CStr(ForceC) + " Force S = " + CStr(ForceS) + " Force Rem = " + CStr(ForceRem)) GoTo ConvFail End If LoopCounter = LoopCounter + 1 End While

    MomentCurvaturePoints(0, k) = k * PhiStep
                MomentCurvaturePoints(1, k) = TotalMoment

                MCPointCount += 1
                MCPercent = CStr(Round(MCPointCount / (MCPoints) * 100, 0)) + "%"

            Next


    That version of the code was what I initially had.  I changed my program to have additional analysis options, thus it was necessary to change the code within the For loop.  I changed it to the following code, which runs about 10x slower:

    For k = 0 To MCPoints
                Phi = k * PhiStep
                TotalForce = AppliedForce + 100 * AcceptableDiff
                Upper = LS_Compression
                Lower = -LS_Tension + Phi * (Abs(CLSLoc - TLSLoc))
                Cpoint = (Upper + Lower) / 2
                LoopCounter = 0
    
                Do While Abs(TotalForce - AppliedForce) > AcceptableDiff
    
                    Strain = 0
                    Stress = 0
                    ForceC = 0
                    MomentC = 0
                    ForceS = 0
                    MomentS = 0
                    ForceRem = 0
                    MomentRem = 0
                    StrainMod = 1
    
                    For j = 0 To MCGrid.GetLength(1) - 1
                        Strain = (Cpoint + Phi * (Abs(CompPegLoc - CLSLoc))) - Phi * (Abs(CompPegLoc - MCGrid(ModGrid, j)))
                        DistFromCenterC = ModCenter + ModArr * MCGrid(ModGrid, j)
                        MCGrid(9, j) = Strain
                        If MCGrid(8, j) = 1 Then
                            Stress = UnconfinedConcrete(Strain)
                            MCGrid(10, j) = Stress
                        ElseIf MCGrid(8, j) = 2 Then
                            If TreatAsUnconf = 0 Then
                                Stress = ConfinedConcrete(Strain)
                            Else
                                Stress = UnconfinedConcrete(Strain)
                            End If
                            MCGrid(10, j) = Stress
                        End If
    
                        MCGrid(11, j) = MCGrid(10, j) * MCGrid(5, j) 'Force
    
                        MCGrid(12, j) = MCGrid(11, j) * DistFromCenterC 'Moment
                        ForceC += MCGrid(11, j)
                        MomentC += +MCGrid(12, j)
                    Next
    
                    For j = 0 To MCReinf.GetLength(1) - 1
                        Strain = Round((Cpoint + Phi * (Abs(CompPegLoc - CLSLoc))) - Phi * (Abs(CompPegLoc - MCReinf(ModReinf, j))), 6)
                        DistFromCenterS = ModCenter + ModArr * MCReinf(ModReinf, j)
    
                        MCReinf(5, j) = Strain
                        If S_SteelModel = 1 Then
                            If Strain < 0 Then
                                StrainMod = -1
                            Else
                                StrainMod = 1
                            End If
                            MCReinf(6, j) = StrainHardeningSteel(Strain * StrainMod) * StrainMod
                        ElseIf S_SteelModel = 2 Then
                            If Strain < 0 Then
                                StrainMod = -1
                            Else
                                StrainMod = 1
                            End If
                            MCReinf(6, j) = MenegottoPinto(Strain * StrainMod) * StrainMod
                        End If
    
                        MCReinf(7, j) = MCReinf(6, j) * MCReinf(4, j)
                        ForceS += MCReinf(7, j)
    
                        MCReinf(8, j) = MCReinf(7, j) * (DistFromCenterS)
                        MomentS += MCReinf(8, j)
    
                        If TreatAsUnconf = 0 Then
                            ForceRem = ForceRem + MCReinf(4, j) * ConfinedConcrete(Strain)
                            MomentRem = MomentRem + MCReinf(4, j) * ConfinedConcrete(Strain) * (DistFromCenterS)
                        Else
                            ForceRem = ForceRem + MCReinf(4, j) * UnconfinedConcrete(Strain)
                            MomentRem = MomentRem + MCReinf(4, j) * UnconfinedConcrete(Strain) * (DistFromCenterS)
                        End If
    
                    Next
    
                    TotalForce = ForceC + ForceS - ForceRem
                    TotalMoment = MomentC + MomentS - MomentRem
    
                    If TotalForce > AppliedForce Then
                        Upper = Cpoint
                        Cpoint = (Lower + Upper) / 2
                    Else
                        Lower = Cpoint
                        Cpoint = (Lower + Upper) / 2
                    End If
    
                    If LoopCounter > MaxIterations Then
                        ConvFailure = 1
                        GoTo ConvFail
                    End If
                    LoopCounter += 1
    
                Loop
    
                MomentCurvaturePoints(0, k) = k * PhiStep
                MomentCurvaturePoints(1, k) = TotalMoment
    
                MCPointCount += 1
                MCPercent = CStr(Round(MCPointCount / (MCPoints) * 100, 0)) + "%"
    
            Next

    I feel like my changed code should run better, but it doesn't.  I know that my code is not written very efficiently (and feel free to comment on ways to improve it), but my main concern is the significant increase in computation time that resulted from my changes.  The loop above is the main block of code within the Sub, which is run via a thread.  In my tests, it is the only thread running at that time.  Everything works, and the computation yields the correct result, but takes 10x longer than previously.  Additionally, the number of iterations does not increase.  So the new code isn't iterating excessively, it is simply taking much longer to compute within each iteration.  Any ideas?  How would I test to find out what line of code is taking a long time to compute?

    Tuesday, April 3, 2012 10:58 PM

Answers

  • I would second (third?) the arguments regarding option (It is very important to have the following set when troubleshooting such issues):

    Option Strict On, Explicit On, Infer off.

    Infer must be OFF: It was an idiotic option to put in there, and devolves the VB language back to VBScript programming style. It WILL cause problems (and there are a few situations where you do need inference, but for simple algorithms it is necessary to turn it off). Remember, Infer allows the COMPILER to decide what type to use, which may not be the type you are expecting, and thus the results may be skewed or completely different from the programmers expectations.

    Regardless, back to the problem in hand: the one thing that jumps out is the variable declaration inside the while loop. While declaration is no problem, they are also initialized inline - this appears to be unnecessary, since the first line of the following loop sets the very same variable (e.g. Strain is set to zero, then subsequently set in the following for loop).

    I notice a Goto - are you not afraid of being viciously eaten by a dinosaur?! There is also a string conversion in a while loop: it looks unnecessary to do so in the loop. While both of these are present in both examples, and don't necessarily apply to your current issue, it is probably something to readdress. Also noted that the second loop uses a 'Round' function, while the first doesn't: is there a specific reason? It doesn't look like it.

    Apart from these obvious coding issues, there doesn't seem to be anything obvious which indicates the first algorithm runs slower than the first. I do suspect type casting if the timing is so far out of line.


    Stephen J Whiteley

    • Marked as answer by Trigg_18 Thursday, April 5, 2012 8:21 PM
    Wednesday, April 4, 2012 12:07 PM
    Moderator
  • The first difference I can see is that you are not specifying a type for those variables that you declare before the first inner loop.  What type are they defaulting to? 

    Set Option Strict On so that you can see where type conversions are occurring.

    Is there any reason for removing the type declaration - that seems like a backward step?  Is that the change you are referring to, or are there other changes?

    You should also confirm that your loop counters (j, k) have defaulted to integer.  Generally, it is not recommended to allow variables to default their type.

    • Edited by Acamar Wednesday, April 4, 2012 6:36 AM sp
    • Proposed as answer by Reed KimbleMVP, Moderator Wednesday, April 4, 2012 9:40 PM
    • Marked as answer by Trigg_18 Thursday, April 5, 2012 8:21 PM
    Wednesday, April 4, 2012 6:31 AM
  • If you care about the speed of your code or the validity of the results, define the methods and variables rather than letting the complier WAG it. 

    Option  Explicit On

    Option Strict On

    Option Infer Off

    Late binding can easily reduce the speed of your code by orders of magnitude.


    Wednesday, April 4, 2012 6:44 AM

All replies

  • All Windows OS systems are Multi programming (the non NT ones like 98 and Millennium), Multi Tasking (the NT ones) or for the oldest (3.1 to 3.12) time slicing ones.

    It means that the OS controls which program is getting the CPU.

    You can set that in a way using the Thread priority. But then still other programs can steal the processor, for instance for important OS requirements.

    http://msdn.microsoft.com/en-us/library/system.threading.thread.priority.aspx

     

    Success
    Cor


    Wednesday, April 4, 2012 6:15 AM
  • The first difference I can see is that you are not specifying a type for those variables that you declare before the first inner loop.  What type are they defaulting to? 

    Set Option Strict On so that you can see where type conversions are occurring.

    Is there any reason for removing the type declaration - that seems like a backward step?  Is that the change you are referring to, or are there other changes?

    You should also confirm that your loop counters (j, k) have defaulted to integer.  Generally, it is not recommended to allow variables to default their type.

    • Edited by Acamar Wednesday, April 4, 2012 6:36 AM sp
    • Proposed as answer by Reed KimbleMVP, Moderator Wednesday, April 4, 2012 9:40 PM
    • Marked as answer by Trigg_18 Thursday, April 5, 2012 8:21 PM
    Wednesday, April 4, 2012 6:31 AM
  • If you care about the speed of your code or the validity of the results, define the methods and variables rather than letting the complier WAG it. 

    Option  Explicit On

    Option Strict On

    Option Infer Off

    Late binding can easily reduce the speed of your code by orders of magnitude.


    Wednesday, April 4, 2012 6:44 AM
  • John,

    Be aware that Option Infer Off has not any influence on speed or late binding. 

    Option Infer infers the normal strong type which could also be used without defining the strong type. 

    For instance.

    Dim x as string = "John" is in fact senseless because "John" is a string therefore with Option Infer On the VB IDE (and C# with a var) makes internally from it a String type. 

    So with Option Infer On 

    Dim x as string = "John" 

    is exactly the same as 

    Dim x = "John"

    Therefore I advice simply to set them all on for optimal speed and realialibility of the resulted assembly.

    (Some find it nicer to use a conservative code style, but that is something different)


    Success
    Cor


    Wednesday, April 4, 2012 9:26 AM
  • Cor:

    If you don''t want to control your code definitions, there is no reason to follow my advice.  Simply reverse my recommendations.  The compiler might make the correct determinations most of the time.

    Wednesday, April 4, 2012 10:14 AM
  • John, 

    It is not me, however you tell it to others where I deny what you wrote about option infer.

    However I follow your advice and do it also strongly to others to put Option Strict On and Option Explicit to ON, the option Infer has no influence on the result, it only makes in my opinion the creation time of code longer if that is set to Off (it is a new one starting at version 2008).


    Success
    Cor


    Wednesday, April 4, 2012 11:20 AM
  • I would second (third?) the arguments regarding option (It is very important to have the following set when troubleshooting such issues):

    Option Strict On, Explicit On, Infer off.

    Infer must be OFF: It was an idiotic option to put in there, and devolves the VB language back to VBScript programming style. It WILL cause problems (and there are a few situations where you do need inference, but for simple algorithms it is necessary to turn it off). Remember, Infer allows the COMPILER to decide what type to use, which may not be the type you are expecting, and thus the results may be skewed or completely different from the programmers expectations.

    Regardless, back to the problem in hand: the one thing that jumps out is the variable declaration inside the while loop. While declaration is no problem, they are also initialized inline - this appears to be unnecessary, since the first line of the following loop sets the very same variable (e.g. Strain is set to zero, then subsequently set in the following for loop).

    I notice a Goto - are you not afraid of being viciously eaten by a dinosaur?! There is also a string conversion in a while loop: it looks unnecessary to do so in the loop. While both of these are present in both examples, and don't necessarily apply to your current issue, it is probably something to readdress. Also noted that the second loop uses a 'Round' function, while the first doesn't: is there a specific reason? It doesn't look like it.

    Apart from these obvious coding issues, there doesn't seem to be anything obvious which indicates the first algorithm runs slower than the first. I do suspect type casting if the timing is so far out of line.


    Stephen J Whiteley

    • Marked as answer by Trigg_18 Thursday, April 5, 2012 8:21 PM
    Wednesday, April 4, 2012 12:07 PM
    Moderator
  • Thanks everyone for the replies.

    First off, I apologize for not mentioning that although I removed the variable declarations from inside the loop, I do declare them just above the loop.  So instead of re-declaring them every loop, I declare them once and then reset the variables at the beginning of each loop.  Is that the best way?  I figured it would be better to declare the variables once outside of the loop.

    I will set those options and see if that helps.  In the For loops, I am assuming I should write it as "For i = 0 As Integer to..." so that I declare the loop counter as an integer?

    And yes, I do notice there are a number of variable definitions within the loop that can be removed.  I will go through it and remove those that I can.

    I did add a number of Round and Abs statements that were not there previously.  The Round functions are necessary in order to make sure values don't fall above a certain criteria.  I found that without the Round function, I would get a Double value that would be 0.0000000001 larger than my maximum allowed value.  I do need a significant number of decimal places, though, as the numbers I am working with are very small.  Would these mathematical operators increase computation time dramatically?

    @SJWhiteley - Can you (or anyone else) explain the problem with using GoTo?  I use this to break the loop if the maximum number of iterations (set by the user) is exceeded.  It directs the code to a statement outside of the loop that throws a message.  However, in my tests, this doesn't happen.  The loop runs within the specified number of iterations and computes successfully.

    Wednesday, April 4, 2012 2:55 PM
  • OK, status update = SOLVED!!

    Again, thanks everyone for the replies.  It seems to have been a lack of type declarations on two arrays declared at the beginning of my sub.  I have two global arrays that have to be modified by various subs at some point throughout the program.  However, when I run certain subs simultaneously using threads, I had to create local copies of the global arrays within each sub so that each sub could run its own modifications without affecting the global array.  The global array is declared as a double.  I did not declare the local array type.  I simply used the Array.Copy function to copy the global array into the local array.  When I changed the code to look like this (adding the As Double to the array declarations), it ran smoothly again.

    Dim MCGrid(Grid.GetUpperBound(0), Grid.GetUpperBound(1)) As Double
    Array.Copy(Grid, MCGrid, Grid.Length)
    Dim MCReinf(Reinf.GetUpperBound(0), Reinf.GetUpperBound(1)) As Double
    Array.Copy(Reinf, MCReinf, Reinf.Length)

    I see now that I should always do this.  I do find it odd, though, that the original code did not declare the arrays As Double, but worked fine.  It is also odd that it was these two arrays that caused the problem.  I had a number of other un-declared types, but it was these two that caused the issue (I commented out the "As Double" on those and the program ran slowly again).

    Some of the previous questions in my post above still stand, and will definitely help me in the future.

    Thanks!

    Wednesday, April 4, 2012 3:47 PM
  • What you are seeing is the problem with not explicitly declaring variables. You (the compiler) are probably declaring the arrays as objects instead of doubles. When you get and set the array values, the casting to and from object data type is very time consuming.

    As far as GOTO is concerned, well, lets just say, it can cause a lot of bugs. While a single goto seems harmless, two don't seem too bad, so three gotos can't be much worse...there doesn't seem to be a problem. Until there's a problem:

    Public Sub DoSomething()
        Dim a() As Long = New Long() {6, 9, 2, 8, 1, 12, 5, 4, 0, 3, 2, 6, 4}
        Call DoSomething(a)
        Dim i As Integer = 0
    12:
        Debug.WriteLine(a(i))
        i = i + 1
        If i < a.Length Then GoTo 12
      End Sub
    
      Public Sub DoSomething(ByVal a() As Long)
        Dim i As Integer = a.Length - 1
        Dim j As Integer = 0
    a4:
        If a(j) > a(j + 1) Then GoTo 3
        j = j + 1
        If j = i Then GoTo 9
        GoTo a4
    9:
        j = 0
        i = i - 1
        If i = 0 Then GoTo 5
    7:
        GoTo a4
    3:
        Dim t As Long
        t = a(j)
        a(j) = a(j + 1)
        a(j + 1) = t
        GoTo 7
    5:
      End Sub

    This example shows several GOTO statements in a very small space, so it shouldn't be too hard to debug. Right?

    Note that the above algorithm is a very simple, trivial, one. But using goto statements makes it pretty much incomprehensible. Goto statements were generally used when no other construct or structure was available. With the current crop of routine constructs, GOTO isn't necessary.

    Indeed, in your code, I can't even see where the GOTO even goes!

    The above snippet was swiped from elsewhere and refuse to, ahem, give credit.


    Stephen J Whiteley

    Wednesday, April 4, 2012 6:24 PM
    Moderator
  • The reason for not using GoTo is that there is a stigma associated with its use.  The use of one GoTo in your code will mark you as an incompetent programmer to many in the field.  VB has so many aliases for GoTo that there is never a reason to use it in VB code.  There are a few instances in C# code where it is useful and it is used extensively in these cases in the .NET framework source code.
    Wednesday, April 4, 2012 6:34 PM
  • My GoTo (only 1 in the sub) was used to exit the while loop and bypass some code to throw an error message (the GoTo took the code to an If-Then at the very end of the sub).  Would it be better to use 'break' to break the while loop and then add additional If-Thens after my loop to test for my convergence failure variable (so that the other bits of code are not run)?

    I understand that it can get pretty hairy debugging if you have a bunch of GoTo's.  But other than GoTo, what kind of statement will allow for sets of code to be bypassed (other than a set of If-Thens to test for a variable)?  I'm just trying to understand whether, if used responsibly, it is an OK tool (and there is simply a stigma associated with it), or whether it is inefficient and there are better methods of accomplishing the task.  The programs I write are for my own use, and I program as sort of a hobby.  That's not to say that I don't want to learn the best way of doing things.  One of the reasons I continue writing programs is to constantly learn more about VB.  I just don't want to toss out a perfectly good tool simply because some people don't like it.  So do people not like it because of the debugging headache it can cause or are there other reasons why it isn't used very much?

    Wednesday, April 4, 2012 7:17 PM
  • ...  But other than GoTo, what kind of statement will allow for sets of code to be bypassed (other than a set of If-Thens to test for a variable)?  ...

    First of all, you can exit out of a loop of any sort by using the "Exit" and then tell it what to exit out of (be careful about that with nested loops), however, if I understand what you're trying to do here, then a better approach would be to throw an exception and include exception handling whatever is the best way/place to to do that. Once an exception is thrown, no more code in the Try/Catch is even attempted (unless it's either in a Finally or after the Try/Catch entirely).
    Wednesday, April 4, 2012 7:24 PM
  • My GoTo (only 1 in the sub) was used to exit the while loop and bypass some code to throw an error message (the GoTo took the code to an If-Then at the very end of the sub).  Would it be better to use 'break' to break the while loop and then add additional If-Thens after my loop to test for my convergence failure variable (so that the other bits of code are not run)?

    As it's a failure, you might want to raise an exception:

    Throw New Exception("Convolution iterations limit exceeded: " & "whatever useful information you can add")

    --
    Andrew

    Wednesday, April 4, 2012 7:28 PM
  • First of all, you can exit out of a loop of any sort by using the "Exit" and then tell it what to exit out of (be careful about that with nested loops), however, if I understand what you're trying to do here, then a better approach would be to throw an exception and include exception handling whatever is the best way/place to to do that. Once an exception is thrown, no more code in the Try/Catch is even attempted (unless it's either in a Finally or after the Try/Catch entirely).

    Thanks for this.  It sounds like a much cleaner approach than what I have.
    Wednesday, April 4, 2012 8:07 PM
  • First off, I apologize for not mentioning that although I removed the variable declarations from inside the loop, I do declare them just above the loop.  So instead of re-declaring them every loop, I declare them once and then reset the variables at the beginning of each loop.  Is that the best way?  I figured it would be better to declare the variables once outside of the loop.

    I will set those options and see if that helps.  In the For loops, I am assuming I should write it as "For i = 0 As Integer to..." so that I declare the loop counter as an integer?

    And yes, I do notice there are a number of variable definitions within the loop that can be removed.  I will go through it and remove those that I can.

    Variable declarations occur at the start of the method regardless of where within the method code you have placed the declaration statement.  So that change would not have done anything, other than force you to determine whether re-initialisation within the block was required (which might be a good thing to be forced to consider). My preference is to declare variables as close to their first use as possible, but whether that is within the loop or just before it is a point of personal style.

    For the For loop you should always specify the type for the loop variable - that removes any risk of the compiler selecting an inappropriate type, and alerts you to code that might be unsuitable for the type that you think is being used.
    • Edited by Acamar Wednesday, April 4, 2012 9:06 PM sp
    Wednesday, April 4, 2012 9:04 PM
  • Thanks for this.  It sounds like a much cleaner approach than what I have.

    Exception handling isn't particularly difficult but it can be confounding sometimes. I found what I think is a good article on it here:

    http://www.codeproject.com/Articles/154121/Using-Try-Catch-Finally

    As I always do when the discussion of exception handling comes up, please take three minutes to watch this video about "Never leaving an empty exception catch!"

    I hope that helps

    Wednesday, April 4, 2012 9:13 PM
  • Exception handling isn't particularly difficult but it can be confounding sometimes. I found what I think is a good article on it here:

    http://www.codeproject.com/Articles/154121/Using-Try-Catch-Finally

    Wow..great article, very well done and easy to follow.  I had already figured out and implemented the Try...Catch block in my program, but that article really helped to explain things.
    Wednesday, April 4, 2012 11:05 PM
  • Wow..great article, very well done and easy to follow.  I had already figured out and implemented the Try...Catch block in my program, but that article really helped to explain things.

    Glad it helped!

    Thursday, April 5, 2012 3:35 AM