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

Programs running slower

19 REPLIES 19
Reply
Message 1 of 20
Anonymous
811 Views, 19 Replies

Programs running slower

Hi All,

I have a simple code in VBA that goeas through al the entities in AutoCAD and hides them. The program runs in 3 seconds. When I upgraded this code to .NET I found out that it runs four time slower than in VBA. It is a simple 10 lines code and it is making the application runs sooo slow. Is this something normal!!

I am worried because if I have a larger .NET program with 100s lines of code then it will be terribly slow to run with AutoCAD.

Any ideas - Thanks
19 REPLIES 19
Message 2 of 20
Anonymous
in reply to: Anonymous

It’s hard to say without seeing the code. A well written routine in VBA will run circles around a poorly written one in .NET
Message 3 of 20
Anonymous
in reply to: Anonymous

Here is the code in .NET:

Public Sub HideAllObjects()
' Get the running instance of AutoCAD. If none
' can be found, just inform the user and quit

On Error Resume Next
moAcad = GetObject(, "AutoCAD.Application")

moAcad.Visible = True
acadDoc = moAcad.ActiveDocument
acadDoc.Application.Visible = True
ThisDrawing = moAcad.ActiveDocument

MsgBox(ThisDrawing.Name)

Dim Entry As AXDBLib.AcadEntity
Dim totEntit As Integer
totEntit = 0

'For Each Entry In moAcad.ActiveDocument.ModelSpace 'ThisDrawing.ModelSpace
For Each Entry In moAcad.ActiveDocument.ModelSpace 'ThisDrawing.ModelSpace
If Entry.Color = 250 Then
Entry.Visible = True

Else

Entry.Visible = False
End If
totEntit = totEntit + 1
Next
Pods.totEntBox.Text = totEntit

moAcad.ActiveDocument.Regen(True)

End Sub Message was edited by: some-1
Message 4 of 20
Anonymous
in reply to: Anonymous

Are you doing it in a stand-alone application to COM-automate Acad (it looks
like it, to me).

If so, of course it is significantly slower than the similar code in Acad
VBA. VBA code run inside Acad, COM automation runs in different process
(your app) and the communication between your app and Acad must pass through
the boundaries of the two process whenever your code refers to an object in
Acad process.

It is not because of .NET. This is the way it is. (BTW, since you use .NET
for the COM automation, there is even a little bit more overhead than
directly use COM technology).


wrote in message news:5641655@discussion.autodesk.com...
Here is the code in .NET:

Public Sub HideAllObjects()
' Get the running instance of AutoCAD. If none
' can be found, just inform the user and quit

On Error Resume Next
moAcad = GetObject(, "AutoCAD.Application")

moAcad.Visible = True
acadDoc = moAcad.ActiveDocument
acadDoc.Application.Visible = True
ThisDrawing = moAcad.ActiveDocument

MsgBox(ThisDrawing.Name)

Dim Entry As AXDBLib.AcadEntity
Dim totEntit As Integer
totEntit = 0

'For Each Entry In moAcad.ActiveDocument.ModelSpace
'ThisDrawing.ModelSpace
For Each Entry In moAcad.ActiveDocument.ModelSpace
'ThisDrawing.ModelSpace
If Entry.Color = 250 Then
Entry.Visible = True

Else

Entry.Visible = False
End If
totEntit = totEntit + 1
Next
Pods.totEntBox.Text = totEntit

moAcad.ActiveDocument.Regen(True)

End Sub

Message was edited by: some-1
Message 5 of 20
Anonymous
in reply to: Anonymous

Hmm looks like your using the COM API with .NET, this could potentially slow things down.
Message 6 of 20
Anonymous
in reply to: Anonymous

Out of process COM is going to run much slower than in process
COM. Also you might want to fix your handler - "On Error Resume Next"
should have been named - "Ah Screw It". If you get an error - your code
will aimlessly fly through - what help is this to users?



wrote in message news:5641655@discussion.autodesk.com...
Here is the code in .NET:

Public Sub HideAllObjects()
' Get the running instance of AutoCAD. If none
' can be found, just inform the user and quit

On Error Resume Next
moAcad = GetObject(, "AutoCAD.Application")

moAcad.Visible = True
acadDoc = moAcad.ActiveDocument
acadDoc.Application.Visible = True
ThisDrawing = moAcad.ActiveDocument

MsgBox(ThisDrawing.Name)

Dim Entry As AXDBLib.AcadEntity
Dim totEntit As Integer
totEntit = 0

'For Each Entry In moAcad.ActiveDocument.ModelSpace
'ThisDrawing.ModelSpace
For Each Entry In moAcad.ActiveDocument.ModelSpace
'ThisDrawing.ModelSpace
If Entry.Color = 250 Then
Entry.Visible = True

Else

Entry.Visible = False
End If
totEntit = totEntit + 1
Next
Pods.totEntBox.Text = totEntit

moAcad.ActiveDocument.Regen(True)

End Sub

Message was edited by: some-1
Message 7 of 20
Anonymous
in reply to: Anonymous

So a .Net version might look like

< CommandMethod("HideAll") > _
Public Shared Sub HideAllDimStuff()
Dim result As PromptSelectionResult = Application.DocumentManager.MdiActiveDocument.Editor.SelectAll
If (result.Status = PromptStatus.OK) Then
Dim idarray As ObjectId() = result.Value.GetObjectIds
Dim tm As TransactionManager = Application.DocumentManager.MdiActiveDocument.Database.TransactionManager
Dim tr As Transaction = tm.StartTransaction
Try
Dim id1 As ObjectId
For Each id1 In idarray
Dim entity1 As Entity = DirectCast(tm.GetObject(id1, OpenMode.ForWrite, True), Entity)
entity1.Visible = False
Next
tr.Commit
Catch obj1 As Object
Application.ShowAlertDialog("Error: Ah Screw It")
Finally
If (Not tr Is Nothing) Then
tr.Dispose
End If
End Try
End If
End Sub
Message 8 of 20
Anonymous
in reply to: Anonymous

Thanks for your useful feedback on this.

Yes. I am trying to create a stand-alone application in .NET with ADT. When I had the same code in VBA it was running supper fast and that was because, as you indicated, VBA code runs inside Acad. Is there any way to pass the boundaries with .NET!!? However, I still think the problem with .NET. I did a little test and upgraded the code to VB6 stand-alone and it is running fast.

I need your advice because my boss wants me to be up to date with .NET. I can continue developing the application as stand-alone in VB6 but what will happen in the future where .NET is replacing VB6.

Thanks for your help
Message 9 of 20
Anonymous
in reply to: Anonymous

I have no idea why you need an external app to automate Acad. As you already
know the slowness is by its nature, although there could be some difference
between .NET app and VB6 app in the regard of degree of the slowness, as I
have already mentioned in previous reply.

Automating Acad is not a very good choice if you have lots of communication
going on between your app and Acad (such as loop through all entities in
drawing, if there is tens of thousands of them). If the whole work process
for a use to use Acad and your app at the same time, automation is even
worse choice if he/she is forced swich between acad and your app back and
forth. IMO, Acad automation is only suitable to batch-processing and a few
other cases.

Acad itself provided very rich probramming API that you can do things
smoothly inside Acad. especially when there is user action involved. If you
have to do thing with automation from external app, then your issue has
little to do with .NET itself (yes, it may be a bit slower than VB6 app).
IMO, There isn't much point to convert a VB6 app that automates Acad to .NET
app in the regard of Acad operation, unless the app does a lot more other
things that can be done better with .NET.

Anyway, if you really have to use automation and the slowness is an issue,
here what I do.

1. make VBA macro to do the heavy CAD job (inside Acad)
2. use external app to link to Acad and the target acadDocument
3. Use the external app to call AcadApplication.RunMacro() to execute the
macro (inside Acad)
4. You may use UserX1-5 system variables to pass some information back and
forth between your App and Acad.

I often use this approach to have an external app to control acad batch
processing. It runs faster, because major Acad operation is run inside ACAD.


wrote in message news:5641760@discussion.autodesk.com...
Thanks for your useful feedback on this.

Yes. I am trying to create a stand-alone application in .NET with ADT. When
I had the same code in VBA it was running supper fast and that was because,
as you indicated, VBA code runs inside Acad. Is there any way to pass the
boundaries with .NET!!? However, I still think the problem with .NET. I did
a little test and upgraded the code to VB6 stand-alone and it is running
fast.

I need your advice because my boss wants me to be up to date with .NET. I
can continue developing the application as stand-alone in VB6 but what will
happen in the future where .NET is replacing VB6.

Thanks for your help
Message 10 of 20
Anonymous
in reply to: Anonymous

Thanks Norman:

I knew this will be a very difficult task. As you said, my application will be constantly looping through 100s of entities in many loops and at the same time accessing an MS Access database. This will tremendously slowdown the program if I am using stand-alone as either VB6 or VB.NET. Really, the application is running fine in VBA inside ADT but my boss wants me (or arguing) that if the automation done outside VBA then:

1) We can use better user interface for the application. For example, better button styles, better meny and list OCX.

2) The user will be able to interact with ADT while running the application such as Zoom-in and Out.

3) We will be able to provide a more professional CD-like installation of our application instead of relying on users loading VBA macros to their project or via menu (*.mns) file.

I totally agree with you that there is no point of doing what I am doing because seriously the application has lots of communication going between ACAD and MS Access DB looping through maybe 1000 entities.

So, I’ll give final test to see my luck and try your suggestion to do split my application to heavy looping stuff in VBA macros inside ACAD. My problem, I do not know how to call VBA macros inside ACAD from my stand-alone application. Can you refer me to an example? Sorry for asking so many questions.

Thank you
Message 11 of 20
Anonymous
in reply to: Anonymous

Hi Danielm,

I inserted your code in my .NET application but I am getting errors. Have I missed some Imports and definitions. I somehow understood that the code is running the AutoCAD 'Command' that automatically select all entities.

What have I missed ... see attached screenshot
Message 12 of 20
Anonymous
in reply to: Anonymous

Hi Norman,

So I managed to run the VBA macro from within my stand-alone application in VB.NET using moAcad.RunMacro("test.dvb!HideAllObjects").

Now how can I pass information from my Application to ACAD and opposite. For example, how do I pass a TextInput value to a macro inside ACAD.

Thanks ...
Message 13 of 20
Anonymous
in reply to: Anonymous

Here try this, make sure you referenced AutoCAD’s managed dlls

Imports System
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.EditorInput
< commandclass="">
Namespace MyClassLibrary
Public Class CRPClass
Private Sub New()
End Sub
< CommandMethod("HideAll") > _
Public Shared Sub HideAllDimStuff()
Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
Dim result As PromptSelectionResult = ed.SelectAll()
If result.Status = PromptStatus.OK Then
Dim idarray As ObjectId() = result.Value.GetObjectIds()
Dim tm As Autodesk.AutoCAD.DatabaseServices.TransactionManager = Application.DocumentManager.MdiActiveDocument.Database.TransactionManager
Using tr As Transaction = tm.StartTransaction()
Try
For Each id1 As ObjectId In idarray
Dim entity1 As Entity = CType(tm.GetObject(id1, OpenMode.ForWrite, True), Entity)
entity1.Visible = False
Next id1
tr.Commit()
Catch
Application.ShowAlertDialog("Error: Ah Screw It")
End Try
End Using
End If
End Sub
End Class
End Namespace
Message 14 of 20
Anonymous
in reply to: Anonymous

Hi Danielm,

I am feeling terribly sorry for keeping asking you all like that but I have no one else to ask. I am also new to VB.NET and not familiar with the CommandMethod to call AutoCAD command from within VB.NET. I used your code again bit I am getting one error as shown in the attached image. I have referenced both acdbmgd.dll and acmgd.dll AutoCAD managed DLLs, but I am still unable to run the code.

I think I am using the Namespace in a wrong VB structure as I am not familiar with it.

Thanks again for your help
Message 15 of 20
Anonymous
in reply to: Anonymous

What version of autocad are you using?
Message 16 of 20
Anonymous
in reply to: Anonymous

I am using ADT 2005
Message 17 of 20
Anonymous
in reply to: Anonymous

There is the problem, Unfortunately the .NET API was very limited with 2005. It would be possible to do this using P/Invoke but, you are probably better off using the ActiveX API as you were. Very sorry about this
Message 18 of 20
Anonymous
in reply to: Anonymous

There are a variety of methods, but in a situation like this I prefer to use VBA's GetSetting() and SaveSetting() functions. These retrieve or store data in a specific area of the Registry under the "HKCU/Software/VB and VBA Program Settings" key, which of course your VB6 or VB.Net app can also reach.

You can even access that data via Visual Lisp in case it's easier to do some of the "heavy lifting" in that language. (the vl-registry-read and vl-registry-write functions)
Message 19 of 20
Anonymous
in reply to: Anonymous

I had a Acad btach automation app used the approach pointed out by Colin
French. The other approach is to used one of some of the User Variables
defined in ACD as System Variable.

Here is psuedo code:

In your VB6/VB.NET stand-alone app:

'Loop through drawings in a list/foder
For i=0 To UBound(FileList)

'Open Drawing
Set Dwg=acadApp.Documents.Open(FileList(i))

'Set User Variable in the drawing so VBA code in macro can read the
input
Dwg.SetVariable("USERS1","MyStringValue")
Dwg.SetVaraible("USERR1",0.00)

'Call VBA MACRO
acadApp.RunMacro "MyMacro"

Dwg.Close False 'or True

Next

In your VBA Macro

Sub MyMacro()

''Ge input from external app
Dim strInput As String
Dim dblInput as Double

strInput=ThisDrawing.GetVariable("USERS1")
dblInput=ThisDrawing.GetVariable("USERR1")

'Validate input
If MyValidateLogic(strInput, dblInput) Then
'If the inputs are valid, do whatever planned
ProcessTheDrawing strInput, dobInput
Else
''If the input is bad, you can write mesaage to a log file
''Or use the same approach to pass error information back to
external app
End If

End Sub

Private Sub ProcessTheDrawing(input as String, input2 As Double)
......
End Sub


Again, I'd try to avoid Acad automation if possible. Even for batch
processing, run inside Acad with LISP,VBA is a lot more faster, and easier
to debug.

The code Danielm showed to you is for Acad ObjectARX .NET API (which is
mainly the topic of this NG), and it run inside Acad. If you want to build
better user interfaces than VBA can do, then you may want to explore
ObjectARX .NET API. Be warned: it is a lot more difficult to learn than VBA
(mainly due to lack of documentation, because Autodesk is so busy to push
its new version yearly, that not bothering to provider documentation any
more), and it is not for stand-alone application.


wrote in message news:5642289@discussion.autodesk.com...
Hi Norman,

So I managed to run the VBA macro from within my stand-alone application in
VB.NET using moAcad.RunMacro("test.dvb!HideAllObjects").

Now how can I pass information from my Application to ACAD and opposite. For
example, how do I pass a TextInput value to a macro inside ACAD.

Thanks ...
Message 20 of 20
Anonymous
in reply to: Anonymous

I think I'll stick to VBA. But I want to thanks you all for your great help. I learned new stuff. Also, I might try a hybrid approach. That is calling dvb macros from within my .NET application.

Thanks you all

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