Author Topic: Fenton Webb's advice re "To dispose or not to dispose"  (Read 74699 times)

0 Members and 1 Guest are viewing this topic.

TheMaster

  • Guest
Re: Fenton Webb's advice re "To dispose or not to dispose"
« Reply #90 on: August 12, 2012, 01:02:49 AM »
Hey guys

a couple of things...

First of all... I posted a new Performance post here http://adndevblog.typepad.com/autocad/2012/08/the-right-tools-for-the-job-autocad-part-5.html

Second of all, if you are in any way confused when to Dispose or not, I have an idea - how about you do *exactly* what TT said not to do (right at the beginning of this post) Dispose absolutely everything!!!! I'm not disrespecting you TT, I'm just running with an idea...

I figure the worst that can happen is your code will cause AutoCAD to simply crash - the good thing though about this approach is, if it crashes it should crash right there and then! I think that is much better than crashing some random place and time when the GC decides kicks in. Also, if it does crash then just tell me! That's because it's a bug, and I'll get it fixed so that it doesn't crash - how does that sound?

Or to put it another way, turn your code into spaghetti.

The point to not disposing things that don't need to be disposed is precisely that (avoiding needlessly complicated code).

If your code crashes, it will probably be a result of a bug that was fostered by your code having become needlessly over-complicated  (as a result of disposing everything), rather than a bug in AutoCAD.

« Last Edit: August 12, 2012, 01:37:09 AM by TT »

Jeff H

  • Needs a day job
  • Posts: 6144
Re: Fenton Webb's advice re "To dispose or not to dispose"
« Reply #91 on: August 12, 2012, 01:20:52 AM »
I have code that plays a squeaker fart noise if I forget to call dispose on object(squeezing the last bit of life out of it) which goes to show you can do anything inside dispose method, and no reason to reply what an ingenious idea that is as it is already understood.
 
So to look at what happens when a line is disposed I can follow the different paths except for one part in DeleteUnmanagedObject.
Where it checks if its ObjectId is null and if so then if the DBObject is Not null I am not sure what that does?
calli


First it checks to see if the ObjectId is null, which means the object is not database-resident.  If the object is not database-resident then it deletes the wrapped AcDbObject.

If the object is database-resident then it calls AcDbObject::close(), which doesn't actually close objects that are transaction-resident.

Thanks Tony,
I looked a while back at it and was not following it and knew I missing something and your earlier post explaining autodelete made me realize what I was missing and then went and looked how it set in constuctor and changed in AddNewlyCreatedObject.

TheMaster

  • Guest
Re: Fenton Webb's advice re "To dispose or not to dispose"
« Reply #92 on: August 12, 2012, 01:32:08 AM »
Hey guys

a couple of things...

First of all... I posted a new Performance post here http://adndevblog.typepad.com/autocad/2012/08/the-right-tools-for-the-job-autocad-part-5.html

Second of all, if you are in any way confused when to Dispose or not, I have an idea - how about you do *exactly* what TT said not to do (right at the beginning of this post) Dispose absolutely everything!!!! I'm not disrespecting you TT, I'm just running with an idea...

I figure the worst that can happen is your code will cause AutoCAD to simply crash - the good thing though about this approach is, if it crashes it should crash right there and then! I think that is much better than crashing some random place and time when the GC decides kicks in. Also, if it does crash then just tell me! That's because it's a bug, and I'll get it fixed so that it doesn't crash - how does that sound?

I'll copy the comments I posted regarding that here:

Quote

Hi Fenton and thanks for the in-depth performance data.

There is one major difference between the Open/Close mechanism and Transaction. When a transaction is disposed, if it was not previously comitted, it results in a call to every resident object's AcDbObject::cancel() memeber (or the functional equivalent of doing that)

Conversely, when a DBObject is disposed, it will always result in a call to AcDbObject::close(), committing any changes made.

So, in the case of using the Open/Close mechanism, what happens when an exception causes control to leave the using() block that disposes a DBObject that was acquired via ObjectId.Open(), was opened for write, and has already had some changes made to it prior to the point where the exception was raised?


And...

Quote

Quote from: fentonwebb
"Now my preferred way, Open/Close – see how much nicer it is?"

That's the problem with apples-to-oranges comparisons. :grin:

Your OpenClose() method and the StartTransaction() method shown above are not functionally-equivalent.

One rolls back changes to all objects that were modified in the foreach() loop in the event that an exception terminates the loop prematurely, while the other does not.


Frankly, I think Albert deserves a bit more credit than you give him, especially in light of the fact that your comparison overlooks a major functional difference between Open/Close and Transactions (in the context of that test code), and I also suspect that Albert's preference for the transaction model may very well be because Transactions facilitate precisely what's overlooked there. And yes, there's a performance cost, but it is nonetheless an apples-to-oranges comparison.


« Last Edit: August 12, 2012, 01:22:06 PM by TT »

TheMaster

  • Guest
Re: Fenton Webb's advice re "To dispose or not to dispose"
« Reply #93 on: August 12, 2012, 03:21:56 PM »

About The Transaction object in AutoCAD... The Transaction model (StartTransaction()) was invented way back when for a specific reason - transacting multiple writes on the same objects(s) and allowing layered rollbacks of these multi-write transactions.

Here’s what I recommend:
If you guys are using StartTransaction(),
and you don’t need the multiple write feature I just mentioned in the above paragraph,
simply change your StartTransaction() to StartOpenCloseTransaction()…


Is anyone able to clarify the distinction regarding transacting multiple writes on the same objects(s)

Regards
Kerry

Transacting multiple writes means that you can repeatedly open a Transaction-resident object for write, regardless of whether it's currently open for write, or not, and the operation succeeds.

However, Regarding OpenCloseTransaction, Fenton hasn't given you the complete picture insofar as making a decision to switch from Transaction to OpenCloseTransaction.

First, there is no native ObjectARX OpenCloseTransaction, and the native transaction management api knows nothing about them.

The implications of that are:

1.  When a DBObject is opened using an OpenCloseTransaction, it's IsTransactionResident property returns false.

2.  When you start an OpenCloseTransaction, the TransactionManager knows nothing about it. For example, its TopTransaction property returns null, its NumberOfActiveTransactions property returns 0, and calls to TransactionManager.GetObject() and ObjectId.GetObject() will both fail.

The major downside of all of this is that you are forced into passing around a transaction, because Autodesk did not bother to integrate OpenCloseTransaction into the core, and the transaction system, so that an active OpenCloseTransaction is transparently-compatible with a regular AcDbTransaction, and similarly accessible through the TransactionManager.

The OpenCloseTransaction was originally a kludge that was implemented entirely in managed code (it simply cached the managed wrappers it previously created in a Dictionary, keyed to their ObjectIds, and returned them when you called GetObject()). The reason it was created was because the code that scanned the current selection to update the ribbon was taking way too long. Subsequently, the OpenCloseTransaction was reimplemented in native code, but was still not integrated into the transaction management system.

The entertaining part of this is how Fenton makes it all seem so incredibly simple, requiring little more than changing calls to StartTransaction(), to StartOpenCloseTransaction() and you're done.

Not so fast. 

That may be true for relatively-simple command implementations that are 'self-contained' and have no dependence on other shared/reusable code libraries. However, if you do make use of shared/reusable code libraries as do I, then you'll almost certainly have a much bigger mess on your hands. For example, if you use helper classes with methods that currently call ObjectId.GetObject() or TransactionManager.GetObject(), they will have to be completely refactored to take a Transaction as a parameter, because Autodesk didn't seem to think there was any need for a means to access a currently-active OpenCloseTransaction through a Database.

So, with regards to Fenton's advice, caveat emptor.

« Last Edit: August 12, 2012, 06:22:50 PM by TT »

Jeff H

  • Needs a day job
  • Posts: 6144
Re: Fenton Webb's advice re "To dispose or not to dispose"
« Reply #94 on: August 12, 2012, 04:01:12 PM »
Gotcha and this suceeds.
 
Code - C#: [Select]
  1.  
  2.          [CommandMethod("InneyOutty")]
  3.         public void InneyOutty()
  4.         {
  5.             Database db = HostApplicationServices.WorkingDatabase;
  6.             ObjectId msId = SymbolUtilityServices.GetBlockModelSpaceId(db);
  7.             Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = db.TransactionManager;
  8.             using (Transaction outerTrx = tm.StartTransaction())
  9.             {
  10.                 BlockTableRecord btr = (BlockTableRecord)outerTrx.GetObject(msId, OpenMode.ForWrite, false, false);
  11.                 BlockTableRecord btr1 = (BlockTableRecord)outerTrx.GetObject(msId, OpenMode.ForWrite, false, false);
  12.                 using (Transaction innerTrx = tm.StartTransaction())
  13.                 {
  14.                     BlockTableRecord btr2 = (BlockTableRecord)innerTrx.GetObject(msId, OpenMode.ForWrite, false, false);
  15.                     innerTrx.Commit();
  16.                 }
  17.                 BlockTableRecord btr3 = (BlockTableRecord)outerTrx.GetObject(msId, OpenMode.ForWrite, false, false);
  18.                 outerTrx.Commit();
  19.             }
  20.         }
  21.  

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Fenton Webb's advice re "To dispose or not to dispose"
« Reply #95 on: August 12, 2012, 05:18:57 PM »
< .. >

Not so fast. 

< .. >


Thanks for the insight Tony.

I had a niggling 'feeling' that there was a reason I hadn't seen widespread use of the OpenCloseTransaction.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

TheMaster

  • Guest
Re: Fenton Webb's advice re "To dispose or not to dispose"
« Reply #96 on: August 12, 2012, 10:33:56 PM »
I am screwing something up for anyone who wants to try to test with code and drawings and results below.
I just do not have the attention span, will or honestly do not care to investigate anything more than a quick slapping together, but tried to make them equal but looking quickly in Reflector looks like you need to use the OpenCloseTransaction object unlike the Transaction object where you can use TransactionManager for GetObject
 
Basically a test using
Open Close method
OpenCloseTransaction
Transaction
 
Here is the code
*******************************************EDIT*********************
Just noticed I open ModelSpace for write in half of them and read for the other


The OpenClose() method you show points out the potential dangers of using the Open/Close mechanism..

To be completely safe when using ObjectId.Open(), one should never call Close() explicitly, unless it is done in the finally block of a try/finally. But it's easier and cleaner to just dispose the DBObject with using(), as shown in the revised version below.

In the case of your OpenClose() method, if an exception were raised while the model space block was open, both it and possibly one of the objects in it would be left open, which would very quickly crash AutoCAD.

Code: [Select]
   [CommandMethod( "OpenClose" )]
   public static void OpenClose()
   {
      Random ran = new Random();
      Stopwatch sw = new Stopwatch();
      int colorIndex = ran.Next( 1, 7 );
      Database db = HostApplicationServices.WorkingDatabase;
      ObjectId msId = SymbolUtilityServices.GetBlockModelSpaceId( db );
      sw.Reset();
      sw.Start();
      using( BlockTableRecord btr = (BlockTableRecord) msId.Open( OpenMode.ForRead ) )
      {
         foreach( ObjectId id in btr )
         {
            using( Entity ent = (Entity) id.Open( OpenMode.ForWrite ) )
            {
               ent.ColorIndex = colorIndex;
            }
         }
      }
      sw.Stop();
      Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage( "\nOpenClose\n" );
      Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage( sw.ElapsedTicks.ToString() );
   }

Last, to see what I was getting at in my comment to Fenton, about Open/Close not being equivalent to using a Transaction, try adding a locked layer to the test drawing, and placing one of the entities on the locked layer.

Then, run OpenClose() (the revised version I show above that is, otherwise this will crash AutoCAD), and when the exception is raised by trying to open the object on the locked layer for write, your command method ends, you are back at the Command: prompt, and notice that some of the entities have had their colors changed, while others haven't.  That's because in the case of the OpenClose() method, there is no transaction, and nothing else to roll back changes made by the code in the command method, and the drawing is left in a partially-altered and potentially corrupt state.
« Last Edit: August 12, 2012, 11:23:15 PM by TT »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Fenton Webb's advice re "To dispose or not to dispose"
« Reply #97 on: August 12, 2012, 11:06:50 PM »

I found some references to OpenCloseTransactions in
AutoCADŽ .NET: Practical Examples of Customizing AutoCAD Entity Behavior
which deals mainly with Overrules.
http://au.autodesk.com/?nd=class&session_id=7560

There is also some reading at Keans Blog, particularly referring to it's usage with Event Handlers

kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Jeff H

  • Needs a day job
  • Posts: 6144
Re: Fenton Webb's advice re "To dispose or not to dispose"
« Reply #98 on: August 13, 2012, 01:45:11 AM »
I am screwing something up for anyone who wants to try to test with code and drawings and results below.
I just do not have the attention span, will or honestly do not care to investigate anything more than a quick slapping together, but tried to make them equal but looking quickly in Reflector looks like you need to use the OpenCloseTransaction object unlike the Transaction object where you can use TransactionManager for GetObject
 
Basically a test using
Open Close method
OpenCloseTransaction
Transaction
 
Here is the code
*******************************************EDIT*********************
Just noticed I open ModelSpace for write in half of them and read for the other


The OpenClose() method you show points out the potential dangers of using the Open/Close mechanism..

To be completely safe when using ObjectId.Open(), one should never call Close() explicitly, unless it is done in the finally block of a try/finally. But it's easier and cleaner to just dispose the DBObject with using(), as shown in the revised version below.

In the case of your OpenClose() method, if an exception were raised while the model space block was open, both it and possibly one of the objects in it would be left open, which would very quickly crash AutoCAD.

Code: [Select]
   [CommandMethod( "OpenClose" )]
   public static void OpenClose()
   {
      Random ran = new Random();
      Stopwatch sw = new Stopwatch();
      int colorIndex = ran.Next( 1, 7 );
      Database db = HostApplicationServices.WorkingDatabase;
      ObjectId msId = SymbolUtilityServices.GetBlockModelSpaceId( db );
      sw.Reset();
      sw.Start();
      using( BlockTableRecord btr = (BlockTableRecord) msId.Open( OpenMode.ForRead ) )
      {
         foreach( ObjectId id in btr )
         {
            using( Entity ent = (Entity) id.Open( OpenMode.ForWrite ) )
            {
               ent.ColorIndex = colorIndex;
            }
         }
      }
      sw.Stop();
      Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage( "\nOpenClose\n" );
      Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage( sw.ElapsedTicks.ToString() );
   }

Last, to see what I was getting at in my comment to Fenton, about Open/Close not being equivalent to using a Transaction, try adding a locked layer to the test drawing, and placing one of the entities on the locked layer.

Then, run OpenClose() (the revised version I show above that is, otherwise this will crash AutoCAD), and when the exception is raised by trying to open the object on the locked layer for write, your command method ends, you are back at the Command: prompt, and notice that some of the entities have had their colors changed, while others haven't.  That's because in the case of the OpenClose() method, there is no transaction, and nothing else to roll back changes made by the code in the command method, and the drawing is left in a partially-altered and potentially corrupt state.

I saw another post you made while "Dining" somewhere else about passing ObjectIds vs Dbobjects and from your LINQ extension methods, it is starting to make sense unless I am completely off which is normal.
For that little example I posted I guess you could UNDO but for starters you would be relying on someone else to UNDO that for you.

This might be a dumb example but if you got a 1000 drawings with Company A standards and you need to map them to Company B standards, and you got some criteria like for blocks with this name on this layer and if on this layer etc...,
And you start opening closing the object then pass the objectid to this function and starts a new transaction and ends that passes the id to another function to do other changes or openclose, etc.....
And you do this in some kinda of batch process and half the transactions fail so you basiclly make half the changes needed then you pretty much just created a 1000 drawings with your own new standards that no longer meet the criteria and can not be mapped.
 
So keeping consistent with your functions and how you go about creating your entry and exit points you can make sure if something goes wrong you can at least can roll back to a state that will not harm or compromise the data?

Is at least a match or a LED light starting to go off?
« Last Edit: August 13, 2012, 01:50:23 AM by Jeff H »

TheMaster

  • Guest
Re: Fenton Webb's advice re "To dispose or not to dispose"
« Reply #99 on: August 13, 2012, 03:59:00 AM »

I saw another post you made while "Dining" somewhere else about passing ObjectIds vs Dbobjects and from your LINQ extension methods, it is starting to make sense unless I am completely off which is normal.
For that little example I posted I guess you could UNDO but for starters you would be relying on someone else to UNDO that for you.


Well, I'm sure everyone would agree that using Open() and Close() (or Dispose) that way is going to become a problem if the code fails, so I guess it's about how one approaches the problem, and whether they plan for failure or always think about what'll happen in the event of a failure, or maybe they're the type that blissfully presumes that their code can't fail, and so they don't have to worry about what happens (e.g., what state the drawing is left in) if it does.

The ObjectARX docs clearly say that acdbOpenAcDbObject() (which is the native counterpart of ObjectId.Open()), is mainly for very 'transient' opening and closing of objects, and that in a scenario like that which your test code falls into, transactions are preferred.

So, the only problem I have is that StartOpenCloseTransaction() poses problems for reusable/modular code, because there is no way to obtain the currently-active OpenCloseTransaction, which just plain sucks if you ask me.

Quote

This might be a dumb example but if you got a 1000 drawings with Company A standards and you need to map them to Company B standards, and you got some criteria like for blocks with this name on this layer and if on this layer etc...,
And you start opening closing the object then pass the objectid to this function and starts a new transaction and ends that passes the id to another function to do other changes or openclose, etc.....
And you do this in some kinda of batch process and half the transactions fail so you basiclly make half the changes needed then you pretty much just created a 1000 drawings with your own new standards that no longer meet the criteria and can not be mapped.
 
So keeping consistent with your functions and how you go about creating your entry and exit points you can make sure if something goes wrong you can at least can roll back to a state that will not harm or compromise the data?

Is at least a match or a LED light starting to go off?

Not sure I follow. Do you mean transactions across multiple files?  I usually have a batch process backup files as each one is processed, so there is a logical transaction and the means to roll back everything, but I'm not sure if that's what you're getting at.

fentonwebb

  • Guest
Re: Fenton Webb's advice re "To dispose or not to dispose"
« Reply #100 on: August 13, 2012, 05:09:01 PM »
Hey TT

"Well, I'm sure everyone would agree that using Open() and Close() (or Dispose) that way is going to become a problem if the code fails, so I guess it's about how one approaches the problem, and whether they plan for failure or always think about what'll happen in the event of a failure, or maybe they're the type that blissfully presumes that their code can't fail, and so they don't have to worry about what happens (e.g., what state the drawing is left in) if it does.
"

I don't agree, the using statement's Dispose is automatically called even when an exception is thrown. Also, there is a Cancel() method on an Opened entity which undoes the changes. This is the same function that a a StartOpenCloseTransaction.Abort() calls.

"The OpenCloseTransaction was originally a kludge that was implemented entirely in managed code (it simply cached the managed wrappers it previously created in a Dictionary, keyed to their ObjectIds, and returned them when you called GetObject()). The reason it was created was because the code that scanned the current selection to update the ribbon was taking way too long. Subsequently, the OpenCloseTransaction was reimplemented in native code, but was still not integrated into the transaction management system."

Hmm you must be listening at my office door or something? :-) The reason that OpenCloseTransaction was implemented was not because of what you say at all, where did you hear that!? The reason we implemented it was because StartTransaction() cannot be used in Event callbacks without great care being taken, also, it's slower than Open/Close. Therefore, so as not to break the transaction model that all have adopted, we wrapped Open/Close in the "transaction" model to give StartOpenCloseTransaction.

"That may be true for relatively-simple command implementations that are 'self-contained' and have no dependence on other shared/reusable code libraries. However, if you do make use of shared/reusable code libraries as do I, then you'll almost certainly have a much bigger mess on your hands. For example, if you use helper classes with methods that currently call ObjectId.GetObject() or TransactionManager.GetObject(), they will have to be completely refactored to take a Transaction as a parameter, because Autodesk didn't seem to think there was any need for a means to access a currently-active OpenCloseTransaction through a Database."

If you using a transaction inside of your library/helper functions, personally, I would never do that, I'd absolutely use Open/Close or StartOpenCloseTransaction in a self contained way. First of all, it's faster, second of all it's not relying on external components being setup, and third it will work in all contexts making it more portable and, less susceptible to change (like TT found).

Kerry, the messages you see when using Open/Close when you compile - quick history lesson - originally, VB.NET did not have a using statement so we adopted the Transaction model for all .NET code and marked Open/Close as Deprecated/Obsolete. Later on, .NET developers became more and more advanced eventually finding the various issues that using raw Transactions brings (slower, cannot be used in Events, cannot be used with HandOverTo, etc etc) so we removed the Deprecated text on Open/Close and made it 'for advanced use only' (hmmm, looks like we accidentally missed a few, sorry about that). We didn't want to make people change their code, so we implemented the OpenCloseTransaction in a Transaction way. It's true you can't use ObjectId.GetObject() by why would you do that when it's not actually using raw Transactions.

One last point, if you call OpenCloseTransaction.Abort() it rolls back any changes by calling the Open/Close Object.Cancel() function - it works almost exactly the same as a raw Transaction under normal circumstances - "Golden Delicious Apple" vs "Granny Smith Apple"?!

"Apples-Oranges"
Yes, Apples-Oranges - but they are still both fruit are they not!!?

Guys, I'm not on here to confuse you all, I want you to succeed - that's my job!!! I think I have been very clear what the differences are between open/close, normal transactions and openclosetransactions. I have also been very clear about when to use Dispose() (I recommend that if you are not sure then, Dispose "always!!!") If you have any specific questions, then why not post them to our AutoCAD .NET forum http://forums.autodesk.com/t5/NET/bd-p/152 - my team are monitoring those much more closely now and we'll be glad to help you guys.

Jeff H

  • Needs a day job
  • Posts: 6144
Re: Fenton Webb's advice re "To dispose or not to dispose"
« Reply #101 on: August 13, 2012, 05:47:23 PM »
Thanks Fenton,
 
VB.NET did not have a using statement so we
VB reminds me of "that guy" who would always come around and hang out and that no one really liked, but just because everyone knew him for so long they just dealt with him and let him hang out, and wished he would just go away
 

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Fenton Webb's advice re "To dispose or not to dispose"
« Reply #102 on: August 13, 2012, 06:11:00 PM »
< ..>

Guys, I'm not on here to confuse you all, I want you to succeed - that's my job!!!
 
< .. >

Thanks for the reply Fenton.

How soon will this information be made public. ?

How soon will AutoDesk samples be brought up to date ?


Regarding my earlier comment about assumptions that are made by commentators, here's a typical example.

Quote
Converting Polyline to Polyline2d
By Augusto Goncalves

There is a method called Polyline.ConvertTo that can convert a lightweight polyline into a polyline 2d object, but this method requires a special treatment.

First, it is required to use StartOpenCloseTransaction method to create a new transaction, instead regular StartTransaction. Second, remove the old polyline and append the newly created polyline 2d.
Code - C#: [Select]
  1. ObjectId plineId = // obtain here...
  2.  
  3. Database db =   Application.DocumentManager.MdiActiveDocument.Database;
  4.  
  5. using (Transaction t =   db.TransactionManager.StartOpenCloseTransaction())
  6.  
  7. {
  8.  
  9.   using (Polyline pline = (Polyline)   t.GetObject(plineId, OpenMode.ForWrite))
  10.  
  11.   {
  12.  
  13.     t.AddNewlyCreatedDBObject(pline, false);
  14.  
  15.     Polyline2d poly2 = pline.ConvertTo(true);
  16.  
  17.     t.AddNewlyCreatedDBObject(poly2, true);
  18.  
  19.     t.Commit();
  20.  
  21.   }
  22.  
  23. }


This statement will make no sense to most people because they have no idea why 'it is required'.
Quote
First, it is required to use StartOpenCloseTransaction method to create a new transaction, instead regular StartTransaction. Second, remove the old polyline and append the newly created polyline 2d.


The reasons for the requirement are not covered in the documentation to my knowledge.

I guess that it has something to do with the AcDbObject::handOverTo() used internally in the wrapped ARX causes problems when used in a conventional Transaction so Open/Close or a StartOpenCloseTransaction must be used.

Can you confirm this please.

Issues like this (and those discussed in the last 100 or so posts) SHOULD be covered prominently in the documentation.

Regards
Kerry






kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

dgorsman

  • Water Moccasin
  • Posts: 2437
Re: Fenton Webb's advice re "To dispose or not to dispose"
« Reply #103 on: August 13, 2012, 06:50:16 PM »
Documentation is one of the first things cut in any budget when project deadlines loom.  I'm not holding my breath on this being any different.   :|

I wonder if they would take volunteer assistance, with appropriate NDA... (no, that wasn't me volunteering!).
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

fentonwebb

  • Guest
Re: Fenton Webb's advice re "To dispose or not to dispose"
« Reply #104 on: August 13, 2012, 07:31:32 PM »
Hey Kerry

here's a tip for you, and all that read here... If you want more details about a function in .NET, simply find the corresponding function in the ObjectARX Reference... Specifically, for the question about OpenCloseTransaction and Polyline2d.ConvertTo - read AcDbPolyline::convertTo()... it states that the second parameter is used as an "Input Boolean indicating whether or not to do a handOverTo between the AcDbPolyline and the AcDb2dPolyline."

Another tip, if you read the ObjectARX Developers guide, you will understand much more about the underlying unmanaged code that the AutoCAD .NET API wraps.