.NET

Reply
Mentor
JamieVJohnson2
Posts: 167
Registered: ‎08-26-2010
Message 1 of 12 (355 Views)

Processing overkill or API bug?

355 Views, 11 Replies
07-24-2012 09:18 AM

I have a routine that runs a cycle through 36 large dynamic blocks, then finishes.  Somewhere in this code I'm either leaking memory, running a never ending loop, or AutoCAD gets stuck on something.  I have a 12gb machine, and this file only uses a few MB on the hard drive.  So even after I save and close the file, AutoCAD is using 100% of 1 core CPU (4 core i7) in 0 drawing state stuck at 11gb of Memory (Private Working Set).  So, What is this program doing in 0 drawing state, and how is my code responsible?  Any advice (good or bad) would be appreciated, I'm looking for clues to clean this up.  I can't even close AutoCAD after running this routine, I have to kill it with task manager.

 

    <CommandMethod("SetCurveOffset")> _
    Public Shared Sub SetCurveOffset()
        Try
            Dim doc As Document = AApplication.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Using lock As DocumentLock = doc.LockDocument()
                Using trans As Transaction = db.TransactionManager.StartTransaction
                    Dim bt As BlockTable = trans.GetObject(db.BlockTableId, OpenMode.ForRead)
                    Dim btrModelSpace As BlockTableRecord = trans.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
                    Dim curves As New List(Of ClearanceCurve)
                    'select curves in drawing
                    Dim psr As Autodesk.AutoCAD.EditorInput.PromptSelectionResult
                    Dim pso As New Autodesk.AutoCAD.EditorInput.PromptSelectionOptions
                    pso.MessageForAdding = "Select Curve-dyn blocks"
                    pso.MessageForRemoval = "Remove Curve-dyn blocks"
                    pso.AllowDuplicates = False
                    pso.SingleOnly = False
                    psr = doc.Editor.GetSelection(pso)
                    If psr.Status = Autodesk.AutoCAD.EditorInput.PromptStatus.OK Then
                        Dim pm As New ProgressMeter
                        pm.SetLimit(psr.Value.Count)
                        pm.Start("Processing Selection")
                        For Each so As Autodesk.AutoCAD.EditorInput.SelectedObject In psr.Value
                            Dim ent As Entity = trans.GetObject(so.ObjectId, OpenMode.ForRead)
                            If TypeOf ent Is BlockReference Then
                                Dim br As BlockReference = ent
                                If br.IsDynamicBlock Then
                                    Dim btrDynBlock As BlockTableRecord = trans.GetObject(br.DynamicBlockTableRecord, OpenMode.ForRead)
                                    If btrDynBlock.Name.Contains(CurveDynBlockName) Then
                                        Dim curve As New ClearanceCurve(br)
                                        curves.Add(curve)
                                    End If
                                End If
                                br = Nothing
                            End If
                            pm.MeterProgress()
                            ent = Nothing
                        Next
                        'each curve is a dynamic block with the cars and loads already attached.
                        'the only thing for this program to do is to set the max clearance offset value.
                        pm.Stop()
                        pm.SetLimit(curves.Count)
                        pm.Start("Calculating Curves")
                        For Each Curve As ClearanceCurve In curves
                            Curve.CalculateClearance(trans)
                            pm.MeterProgress()
                        Next
                        pm.Stop()
                        'that should do it.
                        trans.Commit()
                        pm = Nothing
                    End If
                    bt = Nothing
                    btrModelSpace = Nothing
                    curves = Nothing
                    psr = Nothing
                    pso = Nothing
                End Using
            End Using
            doc = Nothing
            db = Nothing
            System.GC.Collect()
        Catch ex As System.Exception
            MsgBox(ex.ToString)
        End Try

    End Sub

 

 

Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.ApplicationServices
Imports ACApp = Autodesk.AutoCAD.ApplicationServices.Application
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry

Public Class ClearanceCurve

#Region "Properties"

    Property CurveBlock As BlockReference = Nothing
    Property CenterCar As ClearanceCar = Nothing
    Property LeftCar As ClearanceCar = Nothing
    Property RightCar As ClearanceCar = Nothing
    Property Loads As New List(Of ClearanceLoad)
    Property MaxClearanceOffset As Double
    Property TrackHalfWidth As Double
    Property Radius As Double
    Property Degree As Double

    Private maxPoint As Point3d
    Private minPoint As Point3d
    Private maxDist As Double = 0
    Private radCenter As Point3d
    Private pm As ProgressMeter

#End Region

#Region "Load/Save"
    Public Sub New(ByRef curveBlockRef As BlockReference)
        CurveBlock = curveBlockRef
        'dissect this block into its 3 cars, if found, and all other blocks within it
        'any other block is to be considered a load
        ProcessCurveBlock()
    End Sub

    Public Sub New()
        'this is where we intend to have the block and/or ref created by code alone.
    End Sub

#End Region

#Region "Methods"

    Private Sub ProcessCurveBlock()
        Dim doc As Document = ACApp.DocumentManager.MdiActiveDocument
        Dim db As Database = doc.Database
        Using trans As Transaction = db.TransactionManager.StartTransaction
            Dim btr As BlockTableRecord = trans.GetObject(CurveBlock.BlockTableRecord, OpenMode.ForRead)
            Dim mBlockRef As Matrix3d = CurveBlock.BlockTransform
            For Each oid As ObjectId In btr
                Dim ent As Entity = trans.GetObject(oid, OpenMode.ForRead)
                If TypeOf (ent) Is BlockReference Then
                    Dim br As BlockReference = ent
                    Select Case br.Name
                        Case "Car1"
                            'center car
                            CenterCar = New ClearanceCar(br)
                        Case "Car2"
                            'right car
                            RightCar = New ClearanceCar(br)
                        Case "Car3"
                            'left car
                            LeftCar = New ClearanceCar(br)
                        Case Else
                            'special load
                            Loads.Add(New ClearanceLoad(br))
                    End Select
                ElseIf TypeOf (ent) Is Arc Then
                    Dim arc As Arc = ent
                    If arc.ColorIndex = 5 Then
                        radCenter = arc.Center
                    End If
                End If
            Next
            Radius = GetDynamicPropertyValue(CurveBlock, CenterRadiusDynPropertyName)
            Degree = GetDynamicPropertyValue(CurveBlock, DegreeDynPropertyName)
            TrackHalfWidth = CDbl(GetDynamicPropertyValue(CurveBlock, PlateCClearanceDynPropertyName)) / 2
        End Using
    End Sub

    Public Sub CalculateClearance(ByVal trans As Transaction)
        pm = New ProgressMeter
        'find all object endpoints closests to or furthest from radius center
        If CenterCar IsNot Nothing Then
            pm.Start(Me.Degree.ToString & "° Curve - Center Car")
            ProcessBlockReferenceForDistance(CenterCar.BlockRef, trans)
            pm.Stop()
        End If
        If RightCar IsNot Nothing Then
            pm.Start(Me.Degree.ToString & "° Curve - Right Car")
            ProcessBlockReferenceForDistance(RightCar.BlockRef, trans)
            pm.Stop()
        End If
        If LeftCar IsNot Nothing Then
            pm.Start(Me.Degree.ToString & "° Curve - Left Car")
            ProcessBlockReferenceForDistance(LeftCar.BlockRef, trans)
            pm.Stop()
        End If
        For Each load As ClearanceLoad In Loads
            pm.Start(Me.Degree.ToString & "° Curve - Load Block")
            ProcessBlockReferenceForDistance(load.BlockRef, trans)
            pm.Stop()
        Next
        'use max distance value for max clearance
        MaxClearanceOffset = maxDist
        SetMaxClearanceDynProperty(trans)
        pm = Nothing
    End Sub

    Private Sub ProcessBlockReferenceForDistance(ByVal br As BlockReference, ByVal trans As Transaction, Optional ByVal mMasters As List(Of Matrix3d) = Nothing)
        Using trans2 As Transaction = trans.TransactionManager.StartTransaction
            Dim pTest As Point3d
            Using btr As BlockTableRecord = trans2.GetObject(br.BlockTableRecord, OpenMode.ForRead)
                Dim mBlockRef As Matrix3d = br.BlockTransform
                If mMasters Is Nothing Then
                    'first run through - at top level block here
                    mMasters = New List(Of Matrix3d)
                    pm.SetLimit(GetEntityCount(btr, trans2))
                End If
                mMasters.Insert(0, mBlockRef)
                Dim pRadCenterTrans As Point3d = ReverseTransformPoint(radCenter, mMasters)
                For Each oid As ObjectId In btr
                    pm.MeterProgress()
                    Using ent As Entity = trans2.GetObject(oid, OpenMode.ForRead)
                        If Not ent.Layer.ToUpper.Contains("NOPLOT") Then
                            If Not ent.Layer.Contains("03 CEN") Then
                                If Not ent.Linetype.ToUpper.Contains("CENTER") Then
                                    If TypeOf (ent) Is Line Then
                                        ''get endpoints of line and compare to radius center
                                        Dim eLine As Line = ent
                                        TestLine(eLine, mMasters, pRadCenterTrans)
                                        eLine = Nothing
                                    ElseIf TypeOf (ent) Is Circle Then
                                        'use a distance to center type calculation
                                        Dim cir As Circle = ent
                                        pTest = cir.GetClosestPointTo(pRadCenterTrans, False)
                                        TestDistance(pTest, mMasters) 'close point
                                        pTest = cir.Center.Add(pTest.GetVectorTo(cir.Center))
                                        TestDistance(pTest, mMasters) 'far point
                                        cir = Nothing
                                    ElseIf TypeOf (ent) Is Arc Then
                                        'get endpoints and midpoint and compare to radius center
                                        Dim eArc As Arc = ent
                                        TestArc(eArc, mMasters, pRadCenterTrans)
                                        eArc = Nothing
                                    ElseIf TypeOf (ent) Is Polyline Then
                                        'get each vertext and compare to radius center
                                        Dim pline As Polyline = ent
                                        TestPolyLine(pline, mMasters, pRadCenterTrans)
                                        pline = Nothing
                                    ElseIf TypeOf (ent) Is Polyline2d Then
                                        Dim pline2d As Polyline2d = ent
                                        TestPolyLine2D(pline2d, mMasters, pRadCenterTrans)
                                        pline2d = Nothing
                                    ElseIf TypeOf (ent) Is Polyline3d Then
                                        Dim pline3d As Polyline3d = ent
                                        TestPolyLine3D(pline3d, mMasters, pRadCenterTrans)
                                        pline3d = Nothing
                                    ElseIf TypeOf (ent) Is Spline Then
                                        'convert to polyline and compare to radius center
                                        Dim sPline As Spline = ent

                                        Dim p3Coll As Point3dCollection
                                        Dim pLine As Polyline
                                        If sPline.Type = SplineType.ControlPoints Then
                                            sPline = trans2.GetObject(sPline.Id, OpenMode.ForWrite)
                                            sPline.Type = SplineType.FitPoints
                                        End If
                                        Try
                                            pLine = sPline.ToPolylineWithPrecision(50)
                                            TestPolyLine(pLine, mMasters, pRadCenterTrans)
                                        Catch ex As System.Exception
                                            p3Coll = sPline.FitData.GetFitPoints()
                                            For index As Integer = 0 To p3Coll.Count - 1
                                                pTest = p3Coll(index)
                                                TestDistance(pTest, mMasters)
                                            Next
                                        End Try
                                        'test for bridging points
                                        pTest = sPline.GetClosestPointTo(pRadCenterTrans, False)
                                        TestDistance(pTest, mMasters)
                                        sPline = Nothing
                                        p3Coll = Nothing
                                        pLine = Nothing
                                    ElseIf TypeOf ent Is BlockReference Then
                                        Dim brSub As BlockReference = ent
                                        Dim btrSub As BlockTableRecord = trans2.GetObject(brSub.BlockTableRecord, OpenMode.ForRead)
                                        If Not btrSub.Name = CurveCarBlockName Then
                                            'loop on your sub blocks
                                            ProcessBlockReferenceForDistance(brSub, trans2, mMasters)
                                        End If
                                        brSub = Nothing
                                        btrSub = Nothing
                                    End If
                                End If
                            End If
                        End If
                    End Using
                Next
                mMasters.RemoveAt(0)
                mBlockRef = Nothing
            End Using
            pTest = Nothing
        End Using
    End Sub

    Private Sub TestLine(ByVal eLine As Line, ByVal mMasters As List(Of Matrix3d), ByVal pRadCenterTrans As Point3d)
        Dim pTest As Point3d
        ''get endpoints of line and compare to radius center
        pTest = eLine.StartPoint
        TestDistance(pTest, mMasters)
        pTest = eLine.EndPoint
        TestDistance(pTest, mMasters)
        'closest bridging point
        pTest = eLine.GetClosestPointTo(pRadCenterTrans, False)
        TestDistance(pTest, mMasters)
        pTest = Nothing
    End Sub

    Private Sub TestArc(ByVal eArc As Arc, ByVal mMasters As List(Of Matrix3d), ByVal pRadCenterTrans As Point3d)
        'get endpoints and midpoint and compare to radius center
        Dim pTest As Point3d
        'get a point closest to center, just like a circle
        pTest = eArc.GetClosestPointTo(pRadCenterTrans, True)
        'add the vector of this point to the center of the arc
        pTest = eArc.Center.Add(pTest.GetVectorTo(eArc.Center))
        'qualify point
        pTest = eArc.GetClosestPointTo(pTest, False)
        TestDistance(pTest, mMasters)
        'closest bridging point
        pTest = eArc.GetClosestPointTo(pRadCenterTrans, False)
        TestDistance(pTest, mMasters)
        pTest = Nothing
    End Sub

    Private Sub TestPolyLine(ByVal pLine As Polyline, ByVal mMasters As List(Of Matrix3d), ByVal pRadCenterTrans As Point3d)
        Dim pTest As Point3d

        Dim plExplode As New DBObjectCollection
        pline.Explode(plExplode)
        TestDBObjectCollection(plExplode, mMasters, pRadCenterTrans)
        'test for briding points
        pTest = pline.GetClosestPointTo(pRadCenterTrans, False)
        TestDistance(pTest, mMasters)
        pTest = Nothing
        plExplode = Nothing
    End Sub

    Private Sub TestPolyLine2D(ByVal pLine As Polyline2d, ByVal mMasters As List(Of Matrix3d), ByVal pRadCenterTrans As Point3d)
        Dim pTest As Point3d
        Dim plExplode As New DBObjectCollection
        pLine.Explode(plExplode)
        TestDBObjectCollection(plExplode, mMasters, pRadCenterTrans)
        'test for briding points
        pTest = pLine.GetClosestPointTo(pRadCenterTrans, False)
        TestDistance(pTest, mMasters)
        pTest = Nothing
        plExplode = Nothing
    End Sub

    Private Sub TestPolyLine3D(ByVal pLine As Polyline3d, ByVal mMasters As List(Of Matrix3d), ByVal pRadCenterTrans As Point3d)
        Dim pTest As Point3d
        Dim plExplode As New DBObjectCollection
        pLine.Explode(plExplode)
        TestDBObjectCollection(plExplode, mMasters, pRadCenterTrans)
        'test for briding points
        pTest = pLine.GetClosestPointTo(pRadCenterTrans, False)
        TestDistance(pTest, mMasters)
        pTest = Nothing
        plExplode = Nothing
    End Sub

    Private Sub TestDBObjectCollection(ByVal plExplode As DBObjectCollection, ByVal mMasters As List(Of Matrix3d), ByVal pRadCenterTrans As Point3d)
        For Each dbo As DBObject In plExplode
            If TypeOf dbo Is Line Then
                Dim eLine As Line = dbo
                TestLine(eLine, mMasters, pRadCenterTrans)
            ElseIf TypeOf dbo Is Arc Then
                Dim eArc As Arc = dbo
                TestArc(eArc, mMasters, pRadCenterTrans)
            End If
        Next
    End Sub

    Private Sub TestDistance(ByVal pTest As Point3d, ByVal mMasters As List(Of Matrix3d))
        pTest = TransformPoint(pTest, mMasters)
        Dim dTest As Double = pTest.DistanceTo(radCenter)
        'if distance to center is greater than PlateCClearance then:
        If dTest > (Radius + TrackHalfWidth) Then
            'positive distance
            'remove the length to center and only use the offset distance
            dTest = dTest - (Radius + TrackHalfWidth)
            If dTest > maxDist Then
                maxDist = dTest
                maxPoint = pTest
            End If
        ElseIf dTest < (Radius - TrackHalfWidth) Then
            'negative distance
            dTest = (Radius - TrackHalfWidth) - dTest
            If dTest > maxDist Then
                maxDist = dTest
                maxPoint = pTest
            End If
        End If
        dTest = Nothing
    End Sub

    Private Function TransformPoint(ByVal pTest As Point3d, ByVal mMasters As List(Of Matrix3d)) As Point3d
        For Each matrix As Matrix3d In mMasters
            pTest = pTest.TransformBy(matrix)
        Next
        Return pTest
    End Function

    Private Function ReverseTransformPoint(ByVal pTest As Point3d, ByVal mMasters As List(Of Matrix3d)) As Point3d
        If mMasters.Count > 0 Then
            For i As Integer = mMasters.Count - 1 To 0 Step -1
                Dim matrix As Matrix3d = mMasters(i)
                matrix = matrix.Inverse
                pTest = pTest.TransformBy(matrix)
            Next
        End If
        Return pTest
    End Function

    Private Sub SetMaxClearanceDynProperty(ByVal trans As Transaction)
        'use this to force the dynamic block from accidently calculating in the negative, which it may do if you set value to 0, due to double floating point rounding.
        If MaxClearanceOffset < 0.01 Then
            MaxClearanceOffset = 0.01
        Else
            'add one inch total to the offset for safety
            MaxClearanceOffset += ClearanceOffset
        End If
        Using trans2 As Transaction = trans.TransactionManager.StartTransaction
            If CurveBlock IsNot Nothing Then
                If CurveBlock.IsDynamicBlock Then
                    Dim props As DynamicBlockReferencePropertyCollection = CurveBlock.DynamicBlockReferencePropertyCollection
                    For Each prop As DynamicBlockReferenceProperty In props
                        If prop.PropertyName = MaxClearanceOffsetDynPropertyName Then
                            prop.Value = MaxClearanceOffset
                        End If
                    Next
                End If
            End If
            trans2.Commit()
        End Using
    End Sub

 

jvj
Valued Mentor
fieldguy
Posts: 376
Registered: ‎03-31-2005
Message 2 of 12 (348 Views)

Re: Processing overkill or API bug?

07-24-2012 09:43 AM in reply to: JamieVJohnson2

That's quite a bit of code.  The only thing I can suggest is to test this without the progress meters - just to rule that out.

Mentor
JamieVJohnson2
Posts: 167
Registered: ‎08-26-2010
Message 3 of 12 (325 Views)

Re: Processing overkill or API bug?

07-25-2012 01:23 PM in reply to: fieldguy

Thus far, I removed the progress meters, and set my spline to polyline prescision from 50 down to 10.  While that did seem to speed up the processing a bit, niether effected the issue of out of control processing.  After the routine finished, and I get command access back to AutoCAD, the ACAD.exe engine still runs at full core, and won't close down.

 

I may have to meticulously rem out code until i find the offender.  Any other ideas?

 

jvj

jvj
Valued Mentor
AubelecBE
Posts: 394
Registered: ‎01-27-2010
Message 4 of 12 (319 Views)

Re: Processing overkill or API bug?

07-25-2012 02:20 PM in reply to: JamieVJohnson2

hi i am not a expert but i have view fiew leak memory :

in SetCurveOffset : 

Dim pm As New ProgressMeter

....

 

 

Public Sub CalculateClearance(ByVal trans As Transaction)
        pm = New ProgressMeter
pm = Nothing

 

 

My question : where is the Dim for the PM... if it is the same as  in SetCurveOffset you re init the pm .  no?

 

For me, i dont launch transaction --> sub --> new transaction --> sub --> new transaction --> end tr --> return --> end tr --> return --> end tr..

 

I memorise the result of trans for launch another sub with trans in.

 

 

another 'bug' :

Private Sub ProcessBlockReferenceForDistance(ByVal br As BlockReference, ByVal trans As Transaction,

 

how can you pass a transaction with by val ?   and the blockref too ? for me it is a ptr so it is by ref.

.... pm.SetLimit(GetEntityCount(btr, trans2)) --> another init ?  can you stop and dispose then pm before re use it.

 

 

Sorry i am not a pro so i can say wrong.

 

++

 

Valued Mentor
AubelecBE
Posts: 394
Registered: ‎01-27-2010
Message 5 of 12 (316 Views)

Re: Processing overkill or API bug?

07-25-2012 02:36 PM in reply to: AubelecBE

hi. ok  i dont know the ByVal for a pointer...

But how the garbage collector manage the copy of the pointer.... You have a prob of memory no ?

you use copy of pointer in all you sub/function.  copy of transaction, of point3d etc...

 

 

Mentor
JamieVJohnson2
Posts: 167
Registered: ‎08-26-2010
Message 6 of 12 (312 Views)

Re: Processing overkill or API bug?

07-25-2012 03:00 PM in reply to: AubelecBE

Thank you for all your replys.

 

Ok here goes...

1. I remmed out all progress metering and still got this huge memory problem (i have 12 GB ram, shouldn't have any memory problem with ACAD files).

2. I created sub (nested) transactions particularly when I modify a block or dynamic block.  These modifications must be committed before the rest of the code continues, or it may be using old data.  The reason for the nested transaction is so that the entire command's processing can be undone in a single undo command.

3. After stepping through the code, running protions with or without the rest, and running large and small batches, the only thing I'm noticing is that larger batches take a disproportionately long time to process.  On average I'm updating 36 dynamic blocks with 1 property which in the end result move 2 arcs each block.  This usually has taken over 6 minutes to process.  When I step through, and stopped the code between blocks, AutoCAD wouldn't get stuck on anything.  But if I run it without the debugger (VS 2010 Pro) AutoCAD will get stuck in a loop that is not from my code.  With VS 2010 I can hook into an already running AutoCAD and pause it.  If it's running my code, then I get a line of code, if not I get 'external code'.  When running away with itself I get external code on pauses.

 

Due to the large quantity of linework in the tested blocks, the processing is expected to take some time.  If I run this on one block I don't get a problem, but when I run it on all 36 I will.  I'm thinking there is some kind of cleanup or necessary pause and wait I can insert between blocks that may help this.  Any other ideas?

 

jvj

jvj
Mentor
JamieVJohnson2
Posts: 167
Registered: ‎08-26-2010
Message 7 of 12 (310 Views)

Re: Processing overkill or API bug?

07-25-2012 03:03 PM in reply to: AubelecBE

ByVal on a collection object might as well be the same as ByRef, because it will only give me a new memory pointer to the same collection.  It won't clone the collection.  This is generally the same for complex object types.  Transaction is one that works as a byref or byval with the same result.

 

jvj

jvj
Valued Mentor
AubelecBE
Posts: 394
Registered: ‎01-27-2010
Message 8 of 12 (302 Views)

Re: Processing overkill or API bug?

07-26-2012 03:49 AM in reply to: JamieVJohnson2

Sorry no i have tested ByVal and ByRef

 

the Byref give you a pointer . if you modify the data, the new data is transfered

but

ByVal the new data is not transfered..

 

do ByVal Transaction --> you have a copy of transaction but i dont now if you commit the tr. if the commit is done for the tr before enter the sub...

 

If you ByVal a ptr of Point3D you cant change the data inside.. (the function point3D.X is readonly)

but if you use a string (ptr of string) you have a copy of the string not a ptr of the real string (you cant retrieve your new data outside of the sub).

 

 

Mentor
JamieVJohnson2
Posts: 167
Registered: ‎08-26-2010
Message 9 of 12 (296 Views)

Re: Processing overkill or API bug?

07-26-2012 06:59 AM in reply to: JamieVJohnson2

Generally I agree with you, and I wouldn't willingly pass a transaction along as byval (unless I was just getting data, and not putting anything back to the drawing database).  I'll make a pass through the code and look for the passing of transaction to subs and check for byval vs byref (preferred for transaction objects), but I doubt that will have anything to do with my issue.

 

Thanks,

 

jvj

jvj
Mentor
JamieVJohnson2
Posts: 167
Registered: ‎08-26-2010
Message 10 of 12 (295 Views)

Re: Processing overkill or API bug?

07-26-2012 07:15 AM in reply to: JamieVJohnson2

From Microsoft, this may be interesting:

Although the passing mechanism can also affect the performance of your code, the difference is usually insignificant. One exception to this is a value type passed ByVal. In this case, Visual Basic copies the entire data contents of the argument. Therefore, for a large value type such as a structure, it is more efficient to pass it ByRef.

 

In a routine that processes so much stuff switching as much as I can over to byRef, could speed things up.  I'll let you know how it turns out.

 

Thanks,

 

jvj

jvj
Post to the Community

Have questions about Autodesk products? Ask the community.

New Post
Need installation help?

Start with some of our most frequented solutions or visit the Installation and Licensing Forum to get help installing your software.