Seems kind of convoluted if you ask me
I have a question
If StartOpenCloseTransaction() if the preferred operation why have we NOT seen it in any AutoDesk samples in the last 7 years ??
and another ..
>>QuoteRemember to always call Dispose on your AutoCAD.NET objects.<<
would someone care to make a public definitive statement regarding the disposing of objects ?
... and is the process different when using
StartOpenCloseTransaction() ??
Regards
Kerry
Just to make sure I have an understanding is the call to AddNewlyCreatedDBObject() necessary if you already have the line wrapped in the using statement?
Does adding the the line to the transaction just call dispose for you or is there more going on?
My argument is STILL that these concepts and requirements should be covered in the documentation ... but my requests have seemingly fallen on deaf ears.
Seems kind of convoluted if you ask me
What seems kind of convoluted?
Hi Guys,
Stephen is correct. You dont have to use the "using" statement with existing DB resident objects that are opened with the transaction (provided the transaction object is created with the "using" statement).
I originally thought that we need to explicitly dispose off existing DB resident objects as well that are opened with a transaction but because the transaction will be disposed automatically in the UI thread in case of an exception (provided you use the "using" statement with the transaction object), the DB objects openeds with the transaction will also be disposed off properly.
To simplify:
1) Always use the "using" statement with the transaction object
2) Always use the "using" statement with newly created DB Objects being added to the transaction
3) Always using the "using" statement with DB Objects that are not added to the database
4) You dont have to use the "using" statement with existing DB Objects opened with a transaction object
Cheers
Gopinath
Hi,
I have also worked with these Disposable objects but there is not a straight line what objects are MUST to dispose.
Have you read Kean´s article of that? That is the clearest article what I have seen.
http://through-the-interface.typepad.com/through_the_interface/2008/06/cleaning-up-aft.html
http://through-the-interface.typepad.com/through_the_interface/2008/06/cleaning-up-aft.html (http://through-the-interface.typepad.com/through_the_interface/2008/06/cleaning-up-aft.html)
Cheers
Veli V.
Seems kind of convoluted if you ask me
What seems kind of convoluted?
Well, maybe I chose the wrong word .. I tend to do that.
Maybe I just don't see the bigger picture. Disposing of objects when you are done with them is kind of the point isn't it? I thought that the 'using' statement did just that, so why would another disposal be necessary .. unless the concept is that the garbage collector deals with items based upon how they are disposed.
My understanding was that as soon as objects went out of scope, .Net automatically manages the disposal of items not explicitly disposed ... and while it does rely on the garbage collector to do the dirty work, isn't that kind of the point with .Net?
I personally don't recommend leaving unfinished tasks to the GC, instead I like to dispose of items as soon as I am done with them (or as soon as practical). Doing it this way seems straightforward if you ask me ... but apparently others have different ideas ... or maybe that is just the C/C++ programmer speaking.
From my perspective that kinda proves my point .. that being that .Net manages those objects, many times better than the person writing the code would.
Is it possible that Autodesk's managed API is merely a bandaid version? After all, alot of time folks do things just because that is the way they have always done them. Why should Autodesk be any different?
Do you think that total re-write could be done without significantly breaking existing code? And in a timeframe consistent with the rate at which tools, .NET frameworks, etc. are released and retired?
If the DBObject is not database-resident, or is database-resident and you got it from ObjectId.Open(), then you must dispose it.
<snip>
So "TT" - how about you come to Autodesk University this year? We can do a special fun coding class - "Fenton Webb vs TT in AutoCAD .NET Coding Head to Head" - the audience chooses what we code, let's see who does the best job in the shortest time? Come on, it will be fun! I'm sure you will win
One question that came up was when to call Dispose(). The thing is that all of our .NET code wraps ObjectARX, in turn, all of our ObjectARX code is single threaded and the .NET Garbage Collector runs on a background thread... What this means is, if you don't call Dispose() on our AutoCAD .NET objects, you run the high risk of the GC garbage collecting our objects on a background thread, which in turn may cause AutoCAD to crash.
Therefore, I recommend you Dispose() all AutoCAD .NET objects using the .NET 'using' statement – that way you are not relying on the GC to clean up after yourself.
Hey Kerry
I believe in the context I was writing my post it was clear that I was not talking about Dispose()ing objects defined by AutoCAD itself, but if you believe it's misleading then I'll make the post more clear for you, no problem.
< .. >
Hey TT
Actually, I think you misunderstood what I said...
I do mention at the end of that sentence "to cleanup after yourself" - meaning, that you should clean up *YOUR* objects not AutoCAD's.
I noted your comments on the link you posted and I really think it's fairly obvious that you should not dispose of master property objects such as MdiActiveDocument? As common in any computer language, you don't dispose/delete/free objects that are not under your control.
Yes .NET is super cool, but you should still think about what you are doing a bit. Also, the bottom like is that the AutoCAD .NET API wraps ObjectARX, that means you absolutely cannot rely on the GC to Dispose AutoCAD Database objects, and, you shouldn't rely on the GC to Dispose all other AutoCAD .NET classes.
By the way, being careful about cleaning up after your self (not relying on the GC) can be said for alot of Microsofts own .NET API! There are so many things that can't be allowed to be disposed by the GC, how about a file for instance? if you open a file for write, do you rely on the GC to close it? The point is that our AutoCAD .NET API use age requirements are not special by any means.
About The Transaction object in AutoCAD... The Transaction model 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. Back when AutoCAD V1 of .NET was invented, VB.NET did *not* have a using statement so we thought that if we don't allow VBA developers on VB.NET an easy way to control AutoCAD objects we would cost lots of crashes and support calls. This is when AutoCAD .NET Transactions were born, and why we use them.
Now, unfortunately, there is a big overhead creating a Transaction and calling StartTransaction() - this is because it's initializing a whole subsystem which allows this layered writing and undoing mechanism... That's why we have another method called StartOpenCloseTransaction() which is much leaner and faster, you should use that.
When using a Transaction, all objects obtained in the transaction using GetObject() or any objects added to the transaction using AddNewlyCreatedDBObject() do not need to be explicitly Dispose()'s - this is because the Transaction.Commit() does it for you.
If you do not add a newly created object to the transaction using AddNewlyCreatedDBObject, yes, you will have to call Dispose(). However, by not adding it you break the rules of the transaction, so I don't advise that.
So "TT" - how about you come to Autodesk University this year? We can do a special fun coding class - "Fenton Webb vs TT in AutoCAD .NET Coding Head to Head" - the audience chooses what we code, let's see who does the best job in the shortest time? Come on, it will be fun! I'm sure you will win
have little or no prior experience with native ObjectARX/C , something that those of us having that background sometimes mistakenly take for granted.
Fenton, I've been back to re-read the couple of blog posts in question.
http://adndevblog.typepad.com/autocad/2012/07/the-right-tools-for-the-job-autocad-part-3.html
About The Transaction object in AutoCAD... The Transaction model 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. Back when AutoCAD V1 of .NET was invented, VB.NET did *not* have a using statement so we thought that if we don't allow VBA developers on VB.NET an easy way to control AutoCAD objects we would cost lots of crashes and support calls. This is when AutoCAD .NET Transactions were born, and why we use them.
Now, unfortunately, there is a big overhead creating a Transaction and calling StartTransaction() - this is because it's initializing a whole subsystem which allows this layered writing and undoing mechanism... That's why we have another method called StartOpenCloseTransaction() which is much leaner and faster, you should use that.
150,000
OpenClose
5,369,146
OpenCloseTransaction
30,092,959
StartTransaction
10,525,513
StartTransAction&OpenCloseTransaction
11,047,617
1,020,000
OpenClose
37,983,450
OpenCloseTransaction
39,409,458
StartTransaction
72,692,233
150,000
OpenClose
5,688,127
OpenCloseTransaction
5,609,783
StartTransaction
10,439,014
Here, Fenton Webb wrote about the poor speed LISP.
Fenton, I've been back to re-read the couple of blog posts in question.
http://adndevblog.typepad.com/autocad/2012/07/the-right-tools-for-the-job-autocad-part-3.html
In fact, it's not so bad - it all depends on the skill of the programmer and his language skills.
Three years ago, I tested the dictionary in autocad - added dictionaries for 100 mb. My program to emulate the internal dictionary as the SQL database. Speed, compared to an external database, located on the same computer that was ten times faster!
I do not think that the author is equally good command of all the above languages...
How about Delaunay triangulation (http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&sqi=2&ved=0CGwQFjAA&url=http%3A%2F%2Fen.wikipedia.org%2Fwiki%2FDelaunay_triangulation&ei=rLshUMOgLu2p0AGcr4DIDg&usg=AFQjCNEvH2hCZ3uZVJbM8oQRz0q-nEBY2w) ? Would you care to give that a shot ?
Quotegile - "Do I have to dispose the plineCollection (line 18) ?1) Yes
2. Do I have to dispose the regionCollection (line 25) ? And if so, do I have to dispose each region too (line 40)
3. If I dispose each region (line 40), do I need to dispose the regionCollection too (line 25) ?
4. (subsidiary) May I have used StartOpenCloseTransaction() instead of StartTransaction() (line 14) ?"
Hey gile
2) DBObjectCollection should automatically dispose of all 'disposable' objects held within
3) Calling Dispose on the region is fine, but it should not be needed because of (2)
4) Yes[/b]
After Autodesk University I am ready to compete with you, comparing the speed of programs. Choose an interesting problem for the competition.
I am sure, the language just a tool. Speed is gained by algorithms. LISP makes it easier to develop algorithms!
it will be hot 'CHALLENGE' 8-)
I already suggested an interesting problem.
How about Delaunay triangulation (http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&sqi=2&ved=0CGwQFjAA&url=http%3A%2F%2Fen.wikipedia.org%2Fwiki%2FDelaunay_triangulation&ei=rLshUMOgLu2p0AGcr4DIDg&usg=AFQjCNEvH2hCZ3uZVJbM8oQRz0q-nEBY2w) ? Would you care to give that a shot ?
Are you kidding?
Perhaps you are trying to scare me, the complexity of the algorithm?
Here, I'm forced programmers to improve the ARX triangulation that is used in products Autodesk ...
(http://www.theswamp.org/index.php?topic=15784.100)
For complex systems, is important not the language, and the internal algorithms and simplicity.
And you, ever, made its own algorithm for Delaunay triangulation or Voronoi polygons - Chart Tisson?
I already suggested an interesting problem.
excellent!
You have chosen Delaunay triangulation?
I accept the challenge.
My conditions are:
1. test computer with 4 real cores or more.
2. AutoCAD 2013 x64 (without vertical product)
We play with a multi-threaded computing...
ps. I want to compare the performance of algorithms. It makes no sense to compare the performance of AutoCAD.
With impatience I will expect to December!
I see, and how are you going to do parallel execution with LISP?
Oh, and you must open the source code, or no deal.
I see, and how are you going to do parallel execution with LISP?
Oh, and you must open the source code, or no deal.
At Autodesk University in Moscow, I will tell how to use multithreading in AutoLISP ...
It should go without mention, that any solution must be pure LISP, and may not depend on any external API calls or any undocumented APIs.
Hey TT, What you say is totally true, but as I have mentioned before, AutoCAD is *not* thread safe, meaning that if you allow the GC to dispose of AutoCAD objects you run the risk of some AutoCAD code being executed on something otherthan the main thread, which it was never designed for - try it and see what happens - how many of you out there get random crashes happening that you cannot track down...? If you insist on allowing the GC to dispose your AutoCAD class objects, be sure to utilize my blog entry on gcConcurrent - that's my advice.
I do not want to disclose the details to a rival.
But I am sure I will not go to the trick. My solution you are satisfied!
I do not want to disclose the details to a rival.
But I am sure I will not go to the trick. My solution you are satisfied!
Details?
As in AutoCAD Core Console?
... I'd buy tickets to see this one!
Losing team has post all code in VB for a month, with Option explicit and strict off?
Hey TT, What you say is totally true, but as I have mentioned before, AutoCAD is *not* thread safe, meaning that if you allow the GC to dispose of AutoCAD objects you run the risk of some AutoCAD code being executed on something otherthan the main thread, which it was never designed for - try it and see what happens - how many of you out there get random crashes happening that you cannot track down...? If you insist on allowing the GC to dispose your AutoCAD class objects, be sure to utilize my blog entry on gcConcurrent - that's my advice.
I think you misunderstood me :wink:
We already know that managed wrappers whose finalizers execute code that's not thread safe, absolutely must be disposed of determinstically, or kaboom, so I wasn't referring to those cases, but rather the cases where Dispose() is unnecessary and/or pointless, the main one being database-resident DBObjects obtained from a transaction. If you don't dispose them, their finalizers will run on the GC's thread, on another CPU core, and will have no impact on the performance of the code that uses those managed wrappers.
I really don't agree with the advice regarding disabling concurrent garbage collection because that requires the application to wait for it to occur, and I seriously doubt you've investigated what kind of effect a GC can have during user-interactive operations like dragging, and so forth. Covering up a problem in way that impacts performance application-wide is not a professionally-responsible way of dealing with bugs (e.g., failure to Dispose() something). If it is done only as a temporary stopgap measure, then fine, but otherwise, slowing down their application is not a legitimate solution.
... Way to rock out with your nerd out, Jeff! :-P
And it seems that if the DBObjectCollection contains only database-resident objects (plineCollection) or is entirely iterated creating managed wrappers (regionCollection), it do not need to be disposed (none alert from VS in these cases).
My friend Alexander Rivilis said your name behind the nickname TT. I hasten to say, I really respect you for your contribution to programming. Indeed, the competition will be hot and fun!
ps. Yes, I will publish here all the sources. I hope you will too...
Hey TT, What you say is totally true, but as I have mentioned before, AutoCAD is *not* thread safe, meaning that if you allow the GC to dispose of AutoCAD objects you run the risk of some AutoCAD code being executed on something otherthan the main thread, which it was never designed for - try it and see what happens - how many of you out there get random crashes happening that you cannot track down...? If you insist on allowing the GC to dispose your AutoCAD class objects, be sure to utilize my blog entry on gcConcurrent - that's my advice.
I think you misunderstood me :wink:
We already know that managed wrappers whose finalizers execute code that's not thread safe, absolutely must be disposed of determinstically, or kaboom, so I wasn't referring to those cases, but rather the cases where Dispose() is unnecessary and/or pointless, the main one being database-resident DBObjects obtained from a transaction. If you don't dispose them, their finalizers will run on the GC's thread, on another CPU core, and will have no impact on the performance of the code that uses those managed wrappers.
I really don't agree with the advice regarding disabling concurrent garbage collection because that requires the application to wait for it to occur, and I seriously doubt you've investigated what kind of effect a GC can have during user-interactive operations like dragging, and so forth. Covering up a problem in way that impacts performance application-wide is not a professionally-responsible way of dealing with bugs (e.g., failure to Dispose() something). If it is done only as a temporary stopgap measure, then fine, but otherwise, slowing down their application is not a legitimate solution.
Hey TT,
it happens 8-)
I agree with everything you say above.
In addition to your last paragraph, as I said in my blog, "Now, say you are at a customer site where they are experiencing random crashes with your app, or you are running behind schedule and just can’t seem to find the place where the random crash is happening then here’s a quick fix for you – try forcing the GC to run on the Main Thread…"
My friend Alexander Rivilis said your name behind the nickname TT. I hasten to say, I really respect you for your contribution to programming. Indeed, the competition will be hot and fun!
ps. Yes, I will publish here all the sources. I hope you will too...
Thanks.
But, if your intention is to use AutoCAD Core Console as a form of parallel execution, I would not consider that to be a legitimate solution (that is technically multi-processing rather than multi-threading).
Since the LISP garbage collector is not capable of dealing with multiple threads, even if you did find some way to get an entry point on another thread, it would certainly fail given the appropriate stress-testing.
Yes, I'm going to use the console AutoCAD. :-)
Sorry, no deal.
<snip>
So "TT" - how about you come to Autodesk University this year? We can do a special fun coding class - "Fenton Webb vs TT in AutoCAD .NET Coding Head to Head" - the audience chooses what we code, let's see who does the best job in the shortest time? Come on, it will be fun! I'm sure you will win
Yes, I'm going to use the console AutoCAD. :-)
Well hey then, if that sort of solution is acceptable then why pussy-foot around?
Why not just do it in the cloud ? :lmao:
Sorry, no deal.
Yes, I'm going to use the console AutoCAD. :-)
Well hey then, if that sort of solution is acceptable then why pussy-foot around?
Why not just do it in the cloud ? :lmao:
Sorry, no deal.
I'm lost, so this was going to be in native AutoLisp but just running in the command console instead of full blown AutoCAD? Is he using multiple command consoles? Wouldn't native code still be faster multithreading?
Sorry, no deal.
@TT -
Now that this challenge has been answered, I believe there is another challenge (or offer?) previously posed, that has gone unanswered :? :<snip>
So "TT" - how about you come to Autodesk University this year? We can do a special fun coding class - "Fenton Webb vs TT in AutoCAD .NET Coding Head to Head" - the audience chooses what we code, let's see who does the best job in the shortest time? Come on, it will be fun! I'm sure you will win
Pending any personal conflicts of course, would this be something you're willing to entertain?
... I'd very much be interested in the result of this sort of demonstration. Perhaps, if there's enough interest from other members, ADN would even step up, and fly you out? :angel: Just saying.
...Se7en throws down his pop-corn and gets up to ask for a refund to the show. Damn!?
Sorry, no deal.
...*lmao* ...Fall off the turnip truck at least?
Maybe it's true that there's a sucker born every minute, but I ain't one of 'em :grin:
Sorry, no deal.
@TT -
Now that this challenge has been answered, I believe there is another challenge (or offer?) previously posed, that has gone unanswered :? :<snip>
So "TT" - how about you come to Autodesk University this year? We can do a special fun coding class - "Fenton Webb vs TT in AutoCAD .NET Coding Head to Head" - the audience chooses what we code, let's see who does the best job in the shortest time? Come on, it will be fun! I'm sure you will win
Pending any personal conflicts of course, would this be something you're willing to entertain?
... I'd very much be interested in the result of this sort of demonstration. Perhaps, if there's enough interest from other members, ADN would even step up, and fly you out? :angel: Just saying.
Fenton has access to and is quite familiar with the AutoCAD and ObjectARX source code bases.
Maybe it's true that there's a sucker born every minute, but I ain't one of 'em :grin:
Yes, I'm going to use the console AutoCAD. :-)
Well hey then, if that sort of solution is acceptable then why pussy-foot around?
Why not just do it in the cloud ? :lmao:
Sorry, no deal.
I'm lost, so this was going to be in native AutoLisp but just running in the command console instead of full blown AutoCAD? Is he using multiple command consoles? Wouldn't native code still be faster multithreading?
Yes, given comparable algorithms, native code is definitely faster, and may even be faster without parallelism.
Algorithms can be implemented in any language. In fact, most of the best algorithms were not implemented in LISP, and certainly not in AutoLISP, which lacks even the most-basic facilities like arrays. And, because most proven algorithms are developed using languages that do have things like arrays, hashtables, structs, and so on, they tend to be somewhat dependent on those languages.
...Se7en throws down his pop-corn and gets up to ask for a refund to the show. Damn!?
Sorry, no deal....*lmao* ...Fall off the turnip truck at least?
Maybe it's true that there's a sucker born every minute, but I ain't one of 'em :grin:
I refuse to entertain the sort of kludgery that the typical LISP die-hard is willing to resort to in order to justify their existence. :grin:
As far as Fenton goes, give me access to the same things he has access to and I'll clean his clock. :grin:
My friend Alexander Rivilis said your name behind the nickname TT. I hasten to say, I really respect you for your contribution to programming. Indeed, the competition will be hot and fun!
ps. Yes, I will publish here all the sources. I hope you will too...
Thanks.
But, if your intention is to use AutoCAD Core Console as a form of parallel execution, I would not consider that to be a legitimate solution (that is technically multi-processing rather than multi-threading).
Since the LISP garbage collector is not capable of dealing with multiple threads, even if you did find some way to get an entry point on another thread, it would certainly fail given the appropriate stress-testing.
If you recall the story, the original lisp no one was interested, until the show concurrent execution in a network of computers. After that, two years later, was written specification language and the language was fully certified for any use, including defense.
You know Lisp. You should be clear that Lisp is the language of the lists. The meaning of the program - sequential passage through the list items and their computation. But in the lists may be other lists of data and programs. Each calculation can be performed at its core (thread or processor or computer).
If you were tasked for writing code to just run in the CoreConsole and knew it would never be used with acad.exe(I know does not make much sense) and normally would have a coreConsoles running for each core at the same time would that be good candidate for setting gcConcurrent flag and not worrying about disposing everything?
I've noticed that many AutoLISP die-hard enthusiasts, when confronted with the usual criticism about their favorite programming language, often resort to the tactic of confusing AutoLISP with ANSI Common LISP or various other full-featured LISP development tools. What you say about the latter is true - many of them can compile to native code that can run as fast or faster than code compiled from C/C++.
But, please do not confuse those development tools with AutoLISP, which is lame by comparison.
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!!!!
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
< .. >
Autodesk.AutoCAD.DatabaseServices.DBObject.Close()' is obsolete: 'Use Transaction instead'
Autodesk.AutoCAD.DatabaseServices.ObjectId.Open(Autodesk.AutoCAD.DatabaseServices.OpenMode)' is obsolete: 'For advanced use only. Use GetObject instead'
In short, remember that the ticks in Stopwatch are machine/OS dependent, thus you should never count on the ration of Stopwatch ticks to seconds to be the same between two systems, and possibly even on the same system after a reboot. Thus, you can never count on Stopwatch ticks to be the same interval as DateTime/TimeSpan ticks.
To get system-independent time, make sure to use the Stopwatch’s Elapsed or ElapsedMilliseconds properties, which already take the Stopwatch.Frequency (ticks per second) into account.
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()…
!... :-o
I think what I and others newbies are waiting for is a definitive and clear explaination of:
- what absolutely needs to be explictely disposed,
- what doesn't need to be disposed,
- what is a safer practice to dispose to prevent unexcepted situations(i.e. an exception occurs).
I think this could be done with simple and clear samples provided in the AutoCAD .NET Developper's Guide, ObjectARX docs or any other Autodesk publications.
< .. >
.......Oops Thanks!
Note that the returned value is Stopwatch.Ticks not DateTime.Ticks.( see note)
.......
note
http://geekswithblogs.net/BlackRabbitCoder/archive/2012/01/12/c.net-little-pitfalls-stopwatch-ticks-are-not-timespan-ticks.aspx (http://geekswithblogs.net/BlackRabbitCoder/archive/2012/01/12/c.net-little-pitfalls-stopwatch-ticks-are-not-timespan-ticks.aspx)QuoteIn short, remember that the ticks in Stopwatch are machine/OS dependent, thus you should never count on the ration of Stopwatch ticks to seconds to be the same between two systems, and possibly even on the same system after a reboot. Thus, you can never count on Stopwatch ticks to be the same interval as DateTime/TimeSpan ticks.
To get system-independent time, make sure to use the Stopwatch’s Elapsed or ElapsedMilliseconds properties, which already take the Stopwatch.Frequency (ticks per second) into account.
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 (http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.calli.aspx)
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 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 (http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.calli.aspx)
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.
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?
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?
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.
Quote from: http://adndevblog.typepad.com/autocad/2012/08/the-right-tools-for-the-job-autocad-part-5.html
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
< .. >
Not so fast.
< .. >
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
[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() );
}
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?
VB.NET did not have a using statement so weVB 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
< ..>
Guys, I'm not on here to confuse you all, I want you to succeed - that's my job!!!
< .. >
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]
ObjectId plineId = // obtain here... Database db = Application.DocumentManager.MdiActiveDocument.Database; using (Transaction t = db.TransactionManager.StartOpenCloseTransaction()) { using (Polyline pline = (Polyline) t.GetObject(plineId, OpenMode.ForWrite)) { t.AddNewlyCreatedDBObject(pline, false); Polyline2d poly2 = pline.ConvertTo(true); t.AddNewlyCreatedDBObject(poly2, true); t.Commit(); } }
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.
How soon will this information be made public. ?
How soon will AutoDesk samples be brought up to date ?
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.
Sorry,It's hard for me to Search code from the English pages. In our country few people use CADnet so the information is few with Chinese language. In a word, My english is not very good. Thank you for your help.
I can only speak for my DevTech team within Autodesk - but this is why we have started (and will continue) to devote a lot of time to putting as much content as we can in the public domain - but (bugs aside) I'm not planning that we'll be retrofitting any information we post to the DevBlogs into the SDK documentation because to do so would be an expensive/inefficient use of people who could instead be creating much more content on our blogs, developer centers and forums.
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.
Hey TTQuote from: 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.
Now my preferred way, Open/Close – see how much nicer it is?Code - C#: [Select]
public void OpenClose() { Database db = HostApplicationServices.WorkingDatabase; ObjectId msId = SymbolUtilityServices.GetBlockModelSpaceId(db); using (BlockTableRecord btr = (BlockTableRecord)msId.Open(OpenMode.ForRead)) { foreach (ObjectId id in btr) { using (Entity ent = (Entity)id.Open(OpenMode.ForWrite)) { // do something } } } }
Now I have shown the differences between the two styles...
...whereas I think it should give people the basics people need to get started and then those same people can find more advanced info elsewhere (like here).
Hey TT
I personally believe that 99% of code you write for AutoCAD does not need to rollback anything. If it does, more often than not, it's because the code was not implemented correctly. That said, there are completely valid reasons for using nested Transactions with the rollback feature - do you have an example which shows what you are talking about?
Guys,
I'll repeat what I've said before, I personally like to use Open/Close, amongst other reasons, that's my style. Open/Close was in AutoCAD from ObjectARX V1, way before transactions - it works fine and even handles error conditions! For you guys, those who use Transactions, all I'm saying is, there is a big overhead for using "normal" Transactions, if you don't need the nested Transaction/Rollback functionality (99% don't) and you feel your app is running slower than you want, or you are curious if there will be a performance gain, then simply use StartOpenCloseTransaction - it's very simple advice really. If it doesn't work for you, just change it back - Alt+E->Find and Replace->Replace in Files->StartOpenCloseTransaction change to StartTransaction, Match Case, Whole word - simple............... :-)
Not 30 minutes after posting my rant, I have a need to implement two new AcDbCurve members in a custom object that is derived from AcDbCurve. The new members are AcDbCurve::getAcGeCurve() and AcDbCurve::setFromAcGeCurve(). The ObjectARX reference includes the following very informative and helpful description: "This is getAcGeCurve, a member of class AcDbCurve." Google returns one hit to the the DevBlog (http://adndevblog.typepad.com/autocad/2012/04/converting-geometry-objects-to-database-entity.html) which is no help at all. That's it, nothing else.
Therefore, I cannot implement these functions at all. I don't even know whether AcDbCurve implements them. Since only Autodesk knows how to implement them, it's not safe to call the functions on non-Autodesk objects because there is no contract, hence no way to know how to use them correctly. They are effectively unuseable, all because nobody could be bothered to write complete and correct documentation for them.
acdbAssignGelibCurveToAcDbCurve | This function takes an AcGeCurve3d and sets the specified AcDbCurve to be geometrically identical to the AcGeCurve3d. |
acdbConvertAcDbCurveToGelibCurve | This function takes an AcDbCurve and returns an AcGeCurve3d that is geometrically identical to the AcDbCurve. |
acdbConvertGelibCurveToAcDbCurve | This function takes an AcGeCurve3d and returns an AcDbCurve that is geometrically identical to the AcGeCurve3d. |
I don't disagree on the need for formally documentating basic information, dgorsman. I've already made the author of the .NET developers guide aware of this thread. He's going to look into beefing up the info on transactions, and also fixing the places in the sample code where he's 'new'ing DBObjects without a Using statement. He's currently compiling a task list for updating the developers guide, so now is a good time to respond to my invitation to put forward suggestions. Items already on the list are blocks and plotting.
So, if a custom curve class encapsulates an AcGeCurve3d, the above functions should help.
My previous comments were about the AutoCAD API documentation, but I'm happy to pass on your requests/suggestions for other Autodesk products too.
The same applies for any bugs you find in the SDK samples (and if you'd care to summarize to me how the samples are outdated).
On a related note, I agree that the reference guide should do a good job of describing the basic contract for the API. But the days are gone when relatively static SDK and developer guiide samples are the only place people expect to look for code usage information. (Surely people only ever looked there because they couldn't find the information anywhere else)? The first places I (and, I suspect, everyone else on this forum) look for API examples and advice are: blogs (like Through the Interface or DevBlog), forums (like TheSwamp or the Autodesk forums), and websites (like the Autodesk Developer Center or StackOverflow) - or (more generally) we use Google, Bing or whatever is our search engine of choice.
I can only speak for my DevTech team within Autodesk - but this is why we have started (and will continue) to devote a lot of time to putting as much content as we can in the public domain - but (bugs aside) I'm not planning that we'll be retrofitting any information we post to the DevBlogs into the SDK documentation because to do so would be an expensive/inefficient use of people who could instead be creating much more content on our blogs, developer centers and forums.
HTH,
Stephen
And just to reiterate my offer - If someone is interested in sending me a list of documentation omissions and bugs (ideally in order of priority), then I'm very happy to pass it on for you.
My previous comments were about the AutoCAD API documentation, but I'm happy to pass on your requests/suggestions for other Autodesk products too.
Would any of you ARX guys say this is a fair test vs Open Close?
< .. >
For specific documentation bugs, you can use the 'Comment?' link in the ObjectARX helpfiles to report an issue directly to our TechPubs team (if your default browser settings allow it to work properly :|). Failing that, you're welcome to report documentation issues via DevHelp Online (if you're an ADN member) or on the appropriate Autodesk discussion group (if you're an ADN member or if you're not). As Fenton says, my DevTech team are much more actively monitoring the 'API' discussion groups these days.
And (because you know my email address, Kerry :kewl:), you're welcome to send your list of documentation omissions and enhancement requests to me if you like, and I can pass them on to our TechPubs team. They have dedicated API documentation writers, who are quick to fix mistakes or omissions when they are brought to their attention.
< ... >
Stephen
acrxProductKey
is listed in the ObjectARX but is NOT available in the API.
Regards
You got to know when to close’em
And not dispose’em
When to delete’em
And when to walk away