.NET

.NET

Reply
Member
OrgadataPST
Posts: 4
Registered: ‎07-23-2012
Message 1 of 7 (493 Views)

Crash when Transaction takes too long

493 Views, 6 Replies
07-24-2012 11:36 PM

Hello everyone,

 

i have got a problem with AutoCAD 2010 right now. Im having some procedures that take very long to process in between a TransactionManager.StartTransaction and Commit/Abort.

When taking too long AutoCAD sometimes just disappears/crashes without giving a call stack/Exception or anything. There are also no memory leaks or exceptions raised, though i send some status messages to the command line of AutoCAD.

 

Does AutoCAD need anything like a KeepAlive? Do i have to send it some specific messages or anything? Is that a common problem?

Distinguished Mentor
gasty1001
Posts: 582
Registered: ‎04-11-2010
Message 2 of 7 (473 Views)

Re: Crash when Transaction takes too long

07-25-2012 06:52 AM in reply to: OrgadataPST

Hi,

 

Please show the code, and any other relevant information like platform, VS version, .NET Framework, drawing size (posting a sample dwg is very useful) , etc.

 

Gaston Nunez

 

 

Member
OrgadataPST
Posts: 4
Registered: ‎07-23-2012
Message 3 of 7 (469 Views)

Re: Crash when Transaction takes too long

07-25-2012 07:19 AM in reply to: gasty1001

Sadly i can not provide the drawing, because it crashes where the drawing gets generated.

 

VS-Version: 2008 C# Standard

.NET: 3.5

 

And here is the C# code(modified though):

using (Transaction acTransaction = TransactionManager.StartTransaction())
            {
                try
                {
                    CurrentTransaction = acTransaction;

                    BlockTableRecord acBlockTableRecord = acTransaction.GetObject(BlockIds.Peek(),
                            OpenMode.ForWrite) as BlockTableRecord;                    

                    // Create a new object
                    Region acRegion = GetProfileRegion(profile);
                    Polyline3d acPath = GetExtrusionPath(profile.Axis);

                    Solid3d acSolid = new Solid3d();
                    acSolid.SetDatabaseDefaults();
                  
                    acSolid.ExtrudeAlongPath(acRegion, acPath, 0);

                    Solid3d acSlicedSolid = acSolid;
                    try 
                    {
                        SolidAnalyzer.GetFaceNormals(profile, acSolid);
                    }
                    finally
                    {
                        if (acSlicedSolid != null)
                            acSlicedSolid.Color = Autodesk.AutoCAD.Colors.Color.FromColor(profile.OuterColor);
                    }

                    // Append the newly created object to model space and active transaction
                    acBlockTableRecord.AppendEntity(acSlicedSolid);
                    acTransaction.AddNewlyCreatedDBObject(acSlicedSolid, true);

                    acRegion.Dispose();
                    acPath.Erase();

                    // Save changes to database and close transaction
                    acTransaction.Commit();
                    AutoCADApplication.Print("Profile: " + profile.Name + " successfully constructed.");
                }
                catch (Autodesk.AutoCAD.Runtime.Exception ex)
                {
                    AutoCADApplication.Print("Failed to construct profile " + profile.Name
                        + "\n" + ex.Message + "\n\n" + ex.StackTrace);
                    acTransaction.Abort();
                }
                finally
                {
                    CurrentTransaction = null;
                }

 

The GetProfileRegion and GetExtrusionPath Methods always work/never crashed before and i can´t post them for different reasons. The profile region is a highly detailed cut of a window profile.

The SolidAnalyzer class is defined as follows:

public static class SolidAnalyzer
    {
        private static string Vector3dToString(Vector3d vector)
        {
            return "[" +
                vector.X.ToString("F2") + ", " +
                vector.Y.ToString("F2") + ", " +
                vector.Z.ToString("F2")
                + "]";
        }
         
        private static Vector3d GetFaceNormal(Autodesk.AutoCAD.BoundaryRepresentation.Face face, Point3d point)
        {
            PointOnSurface ptOnSurf = face.Surface.GetClosestPointTo(point);
         
            Point2d param = ptOnSurf.Parameter;
         
            Vector3d normal = ptOnSurf.GetNormal(param);         
            Vector3d normalTest = normal.MultiplyBy(1E-6 / normal.Length);
          
            Point3d ptTest = point.Add(normalTest);
         
            PointContainment ptContainment = new PointContainment();
         
            bool reverse = false;
         
            using(BrepEntity brepEnt = face.Brep.GetPointContainment(ptTest, out ptContainment))
            {
                if(ptContainment != PointContainment.Outside)
                {
                    reverse = true;
                }
            }
         
            return normal.MultiplyBy(reverse ? -1.0 : 1.0);
        }

        public static List<Vector3d> GetFaceNormals(Profile profile, Solid3d profileSolid)
        {
            List<Vector3d> faceNormals = new List<Vector3d>();

            using (Brep brep = new Brep(profileSolid))
            {
                foreach (Autodesk.AutoCAD.BoundaryRepresentation.Face face in brep.Faces)
                {
                    PointContainment ptContainment = new PointContainment();

                    using (BrepEntity brepEnt = face.GetPointContainment(new Point3d(0, 0, 0), out ptContainment))
                    {
                        faceNormals.Add(GetFaceNormal(face, new Point3d(0, 0, 0)));

                        //if (ptContainment == PointContainment.Inside ||
                        //    ptContainment == PointContainment.OnBoundary)
                        {
                            AutoCADApplication.Print("\nFace Normal at " +
                                "[0, 0, 0] = " + Vector3dToString(GetFaceNormal(face, new Point3d(0, 0, 0))));
                        }
                    }
                }
            }

            return faceNormals;
        }
    }

 

After adding the SolidAnalyzer class and using GetFaceNormals AutoCAD sometimes first freezes/does not respond and then crashes or disappears after some normals have been written to the commandline.

 This procedure takes very long because the solid3d has >300 faces most of the time.

 

 

ADN Support Specialist
fenton.webb
Posts: 352
Registered: ‎07-24-2007
Message 4 of 7 (435 Views)

Re: Crash when Transaction takes too long

07-30-2012 04:14 PM in reply to: OrgadataPST

I have not run your code to test what's going on exactly, but i can guess just looking... Please see my comments below...

 

using (Transaction acTransaction = TransactionManager.StartTransaction())

{

    try

    {

        CurrentTransaction = acTransaction;

 

        BlockTableRecord acBlockTableRecord = acTransaction.GetObject(BlockIds.Peek(),

                OpenMode.ForWrite) as BlockTableRecord;                   

 

        // Fenton : you must dispose all AutoCAD objects before

        // this function goes out of scope, use using. Otherwise those objects will be disposed by the GC on a worker thread, which will most likely crash AutoCAD

        using (Region acRegion = GetProfileRegion(profile))

        {

          using (Polyline3d acPath = GetExtrusionPath(profile.Axis))

          {

            using (Solid3d acSolid = new Solid3d())

            {

              acSolid.SetDatabaseDefaults();                 

              acSolid.ExtrudeAlongPath(acRegion, acPath, 0);

 

              // Fenton: what does this line mean? if you are trying

              // to make a copy, think again because it won't

              //Solid3d acSlicedSolid = acSolid;

 

              // Fenton: this is better

              Solid3d acSlicedSolid = new Solid3d();

              acSlicedSolid.CopyFrom(acSolid);

 

              try

              {

                  SolidAnalyzer.GetFaceNormals(profile, acSolid);

              }

              finally

              {

                  if (acSlicedSolid != null)

                      acSlicedSolid.Color = Autodesk.AutoCAD.Colors.Color.FromColor(profile.OuterColor);

              }

 

              // Append the newly created object to model space and active transaction

              acBlockTableRecord.AppendEntity(acSlicedSolid);

              acTransaction.AddNewlyCreatedDBObject(acSlicedSolid, true);

 

              acPath.Erase();

            }

          }

        }

 

        // Save changes to database and close transaction

        acTransaction.Commit();

        AutoCADApplication.Print("Profile: " + profile.Name + " successfully constructed.");

    }

    catch (Autodesk.AutoCAD.Runtime.Exception ex)

    {

        AutoCADApplication.Print("Failed to construct profile " + profile.Name

            + "\n" + ex.Message + "\n\n" + ex.StackTrace);

        acTransaction.Abort();

    }

    finally

    {

        CurrentTransaction = null;

    } 

 

 





Fenton Webb

Developer Technical Services

Autodesk Developer Network


ADN Support Specialist
fenton.webb
Posts: 352
Registered: ‎07-24-2007
Message 5 of 7 (434 Views)

Re: Crash when Transaction takes too long

07-30-2012 04:30 PM in reply to: fenton.webb

I also just posted this for you guys...

 

http://adndevblog.typepad.com/autocad/2012/07/forcing-the-gc-to-run-on-the-main-thread.html





Fenton Webb

Developer Technical Services

Autodesk Developer Network


Member
OrgadataPST
Posts: 4
Registered: ‎07-23-2012
Message 6 of 7 (415 Views)

Re: Crash when Transaction takes too long

07-31-2012 12:12 AM in reply to: fenton.webb

Thanks, Fenton.

The line where it says acSlicedSolid= ... was just a remain of a slicing procedure i commented out to test, sadly i forgot that line. It wasn´t intended to copy anything, it´s not a struct. Was used to determine which Solid3d to be cut because it was cut multiple times and that one was just a pointer to it.

 

Anyways, the GC won´t collect them in this case cause the objects are still referenced and using "using" doesn´t solve it either. I´ve just splitted it into multiple small transactions now and somehow it works. 


I can´t really tell why though..., thanks a lot for the help.

 

 

ADN Support Specialist
fenton.webb
Posts: 352
Registered: ‎07-24-2007
Message 7 of 7 (401 Views)

Re: Crash when Transaction takes too long

07-31-2012 09:05 AM in reply to: OrgadataPST

No problem.

 

If you post a working sample project, I'll take a look at it for you.





Fenton Webb

Developer Technical Services

Autodesk Developer Network


Post to the Community

Have questions about Autodesk products? Ask the community.

New Post
Announcements
Do you have 60 seconds to spare? The Autodesk Community Team is revamping our site ranking system and we want your feedback! Please click here to launch the 5 question survey. As always your input is greatly appreciated.