.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Crash when Transaction takes too long

6 REPLIES 6
Reply
Message 1 of 7
OrgadataPST
1197 Views, 6 Replies

Crash when Transaction takes too long

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?

6 REPLIES 6
Message 2 of 7
hgasty1001
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

 

 

Message 3 of 7
OrgadataPST
in reply to: hgasty1001

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.

 

 

Message 4 of 7
fenton.webb
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
AutoCAD Engineering
Autodesk

Tags (1)
Message 5 of 7
fenton.webb
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
AutoCAD Engineering
Autodesk

Message 6 of 7
OrgadataPST
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.

 

 

Message 7 of 7
fenton.webb
in reply to: OrgadataPST

No problem.

 

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




Fenton Webb
AutoCAD Engineering
Autodesk

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost