Hot News:

Mit Unterstützung durch:

  Foren auf CAD.de (alle Foren)
  AutoCAD ObjectARX und .NET
  langsames Lesen von Blöcken

Antwort erstellen  Neues Thema erstellen
CAD.de Login | Logout | Profil | Profil bearbeiten | Registrieren | Voreinstellungen | Hilfe | Suchen

Anzeige:

Darstellung des Themas zum Ausdrucken. Bitte dann die Druckfunktion des Browsers verwenden. | Suche nach Beiträgen nächster neuer Beitrag | nächster älterer Beitrag
  
Gut zu wissen: Hilfreiche Tipps und Tricks aus der Praxis prägnant, und auf den Punkt gebracht für Autodesk Produkte
Autor Thema:  langsames Lesen von Blöcken (3127 mal gelesen)
bennyboss
Mitglied



Sehen Sie sich das Profil von bennyboss an!   Senden Sie eine Private Message an bennyboss  Schreiben Sie einen Gästebucheintrag für bennyboss

Beiträge: 15
Registriert: 07.11.2005

ThinkPad 60, OS: Vista Business, CPU: 1,86 Core 2 Duo, RAM: 2GB, AutoCAD: 2008, VisualStudio2005

erstellt am: 12. Apr. 2007 15:33    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat    Unities abgeben: 1 Unity (wenig hilfreich, aber dennoch)2 Unities3 Unities4 Unities5 Unities6 Unities7 Unities8 Unities9 Unities10 Unities

Hallo, ich brauche wieder ein kleines Tipp von euch,

das Problem: ich möchte in meinem C# Programm alle Blöcke einer Zeichnung zählen... das macht mein Programm richting nur sehr sehr langsam, da manche Blöcke andere Blöcken enthalten können, benutzte ich um sie alle zu finden eine Rekurrenz-Funktion, dann zähle ich entsprechend alles was ich gefunden habe

irgendwie benutzt AutoCAD immer 50% von der CPU Leistung (Core 2 Duo) (XPro, AutoCAD2007) während diese Rekurrenz-Funktion ausgeführt wird... obwohl sie oft nicht mehr als 50 Mal hintereinader gerufen wird wenn ein Block komplizierter ist

auf das laufende AutoCAD Instanz greife ich von C# mit Marshal.GetActiveObject("AutoCAD.Application.17") zu

ist es möglich diese Rekurrenz-Funktion zu beschleunigen? wenn ja dann wie?

und eine ausweichende Lösung die mir so eingefallen ist: ich dachte man könnte sie zB in ein ARX-Programm reinpacken und sie dann extern von meinem Programm wenn nötig ausführen?... da ich aber mit ARXen noch nicht gearbeitet habe weiss ich nicht ob es sich der Aufwand loht... ginge so was?

[Diese Nachricht wurde von bennyboss am 12. Apr. 2007 editiert.]

Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP

Jonapap
Mitglied



Sehen Sie sich das Profil von Jonapap an!   Senden Sie eine Private Message an Jonapap  Schreiben Sie einen Gästebucheintrag für Jonapap

Beiträge: 206
Registriert: 18.08.2006

erstellt am: 16. Apr. 2007 18:19    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat    Unities abgeben: 1 Unity (wenig hilfreich, aber dennoch)2 Unities3 Unities4 Unities5 Unities6 Unities7 Unities8 Unities9 Unities10 Unities Nur für bennyboss 10 Unities + Antwort hilfreich

Hallo bennyboss,

wenn ich dich richtig verstanden habe, dann bindest du dein Programm nicht als dll in Acad ein sondern greifst mit einem exe-Programm auf die aktuelle Sitzung zu.
Das Problem hierbei ist, das Zugriffe auf die Datenbank von Acad über ein externes Programm wesentlich langsamer ablaufen (um Faktor 80x langsamer) als wenn die Funktion direkt in Acad eingebunden ist.

Lösung: Funktion als dll einbinden (C#.Net-Dll mit "netload" einbinden), mit dem internen VBA arbeiten oder das ganze als Lisp-Programm laufen lassen.

Falls du die Blöcke über ein Selectionset-Object suchst: Das müsste über einen direkten Zugriff auf die Datenbank viel schneller gehen.
Document.Blocks.count dürfte dir dabei behilflich sein.

------------------
Gruß
Markus

Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP

bennyboss
Mitglied



Sehen Sie sich das Profil von bennyboss an!   Senden Sie eine Private Message an bennyboss  Schreiben Sie einen Gästebucheintrag für bennyboss

Beiträge: 15
Registriert: 07.11.2005

ThinkPad 60, OS: Vista Business, CPU: 1,86 Core 2 Duo, RAM: 2GB, AutoCAD: 2008, VisualStudio2005

erstellt am: 21. Apr. 2007 12:19    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat    Unities abgeben: 1 Unity (wenig hilfreich, aber dennoch)2 Unities3 Unities4 Unities5 Unities6 Unities7 Unities8 Unities9 Unities10 Unities

Hi Jonapap, vielen Dank für deine Antwort,

nach alldem was ich noch gefunden habe bin ich noch mehr verwirrt,

also eine ARX-Datei ist eine DLL nur die Endung ist anders, aber das ist nicht das gleiche wie eine DLL erstellt mit C# und mit DLL-Endung denn das wird mit netload geladen und lässt sich nicht debugen usw. dagegen mit ARXen kann man fast alles machen

auf der Website von Autodesk steht: "The ObjectARX® programming environment provides object-oriented C++, C# and VB .NET application programming interfaces for developers to use, customize, and extend AutoCAD® software..."

warum ist es denn nur so schwer etwas über ARXen in C# zu finden? in der Dokumentation konnte ich auch nichts vernünftiges finden...

manche Webseiten bechaupten man müsse COM benutzten wenn man ARX in C# schreiben will, leider sagt keine von denen ob so eine ARX-Datein dann genau so schnell ist wie Lisp oder VBA 

[Diese Nachricht wurde von bennyboss am 21. Apr. 2007 editiert.]

Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP

Jonapap
Mitglied



Sehen Sie sich das Profil von Jonapap an!   Senden Sie eine Private Message an Jonapap  Schreiben Sie einen Gästebucheintrag für Jonapap

Beiträge: 206
Registriert: 18.08.2006

erstellt am: 21. Apr. 2007 14:33    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat    Unities abgeben: 1 Unity (wenig hilfreich, aber dennoch)2 Unities3 Unities4 Unities5 Unities6 Unities7 Unities8 Unities9 Unities10 Unities Nur für bennyboss 10 Unities + Antwort hilfreich

Hallo bennyboss,

1. Eine Arx-Datei ist eine mit Visual C++ kompilierte dll-Datei

2. Man kann nur mit Visual C++ auf die Objekt-ARX-Klasse zugreifen.

3. Mit C# oder Visual-Basic kann man über die COM-Schnittstelle Autocad steuern. Auf COM basierte dll's können jedoch soweit ich weiß nur über Autocad-VBA angesprochen werden. Haben dann jedoch kaum Nachteile bei der Performance.

4. Mit .Net (vb.Net,C#.Net ...) kann man über die sogenannten wrapped Classes Autocad steuern. Die so erzeugten dll's lassen sich ohne Tricks (http://discussion.autodesk.com/thread.jspa?messageID=4531456) nur mittels Netload in Autocad laden.

5.Dll's die auf Objekt-ARX oder wrapped Classes basieren können nur direkt in Autocad eingebunden werden. Eine Steuerung aus externen Programmen ist nur über die COM-Schnittstelle möglich und ist dann deutlich langsamer, als wenn die dll's direkt in Acad eingebunden werden.

Mögliche Lösung für dein Problem:
Die in Autocad eingebundene dll greift selbst auf deine Datenbank zu und speichert dort die Daten die du brauchst 

------------------
Gruß
Markus

Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP

bennyboss
Mitglied



Sehen Sie sich das Profil von bennyboss an!   Senden Sie eine Private Message an bennyboss  Schreiben Sie einen Gästebucheintrag für bennyboss

Beiträge: 15
Registriert: 07.11.2005

ThinkPad 60, OS: Vista Business, CPU: 1,86 Core 2 Duo, RAM: 2GB, AutoCAD: 2008, VisualStudio2005

erstellt am: 22. Apr. 2007 20:36    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat    Unities abgeben: 1 Unity (wenig hilfreich, aber dennoch)2 Unities3 Unities4 Unities5 Unities6 Unities7 Unities8 Unities9 Unities10 Unities

ich muss mich noch mal bei Dir für die ausführliche Erklärung bedanken   

wie ich sehe ist das ganze so kompliziert und verwirrend  dass es wohl einfacher wäre wenn ich mich mit C++ und MFC und VC++ beschäftige um ObjectARX Programme zu schreiben als sich den Kopf mit dieser ganzen noch unsinnigen Implementation von wrapped Classes für .NET zu zerbrechen

das aller schlimmste daran ist dass man bei jeder Änderung AutoCAD neustarten muss... es ist doch unmöglich beim ersten Mal ein fehlerfreies dll-Programm zu schreiben

bis ich soweit mit C++ bin schreibe ich diese BlockCount-Funktion einfach in VBA um

------------------
( ... bennyboss ... )

Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP

Jonapap
Mitglied



Sehen Sie sich das Profil von Jonapap an!   Senden Sie eine Private Message an Jonapap  Schreiben Sie einen Gästebucheintrag für Jonapap

Beiträge: 206
Registriert: 18.08.2006

erstellt am: 23. Apr. 2007 07:30    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat    Unities abgeben: 1 Unity (wenig hilfreich, aber dennoch)2 Unities3 Unities4 Unities5 Unities6 Unities7 Unities8 Unities9 Unities10 Unities Nur für bennyboss 10 Unities + Antwort hilfreich

Zitat:
Original erstellt von bennyboss:
das aller schlimmste daran ist dass man bei jeder Änderung AutoCAD neustarten muss... es ist doch unmöglich beim ersten Mal ein fehlerfreies dll-Programm zu schreiben
[/i]

In .Net gibt es die Möglichkeit beim debuggen "Edit and Continue" zu verwenden. Solange du nur innerhalb der Subs oder Functions editierst und noch keine Formulare benutzt, kannst du also bei gestartetem Acad deinen Code editieren und anschließend sofort in Acad testen

Bei Objekt-Arx gibt's dass bestimmt auch.

Blöd ist allerdings die äußerst dürftige Dokumentation (Acad SDK) zu wrapped Classes und zu ObjektArx. Viele Infos dazu findet man nur in englischsprachigen Foren (z.B. http://discussion.autodesk.com/index2.jspa?categoryID=8)

------------------
Gruß
Markus

Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP

bennyboss
Mitglied



Sehen Sie sich das Profil von bennyboss an!   Senden Sie eine Private Message an bennyboss  Schreiben Sie einen Gästebucheintrag für bennyboss

Beiträge: 15
Registriert: 07.11.2005

ThinkPad 60, OS: Vista Business, CPU: 1,86 Core 2 Duo, RAM: 2GB, AutoCAD: 2008, VisualStudio2005

erstellt am: 23. Apr. 2007 10:12    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat    Unities abgeben: 1 Unity (wenig hilfreich, aber dennoch)2 Unities3 Unities4 Unities5 Unities6 Unities7 Unities8 Unities9 Unities10 Unities

obwohl ich das "Edit and Continue" natürlich kenne hat mir das noch in AutoCAD gefehlt, ich habe einbisschen gegooglet und so was gefunden: (Debug .NET dll's in AutoCAD 2007) http://jtbworld.blogspot.com/2006/04/debug-net-dlls-in-autocad-2007.html  und dann noch http://discussion.autodesk.com/thread.jspa?messageID=5155209

die Einstellungen in VisualStudio habe ich entsprechend verändert und wie im zweiten Link berschrieben starte ich jetzt AutoCAD mit "Start external program", wenn ich jetzt einen Breakpunkt setzte hält das Programm auch und das Edit and Contiune funktioniert wie vorgesehen


eine Sache ist trotzdem noch etwas ärgerlich, ich muss eine Zeichnung und die DLL vom Hand laden, die Frage: wie kann ich AutoCAD überreden automatisch meine DLL-Datei zu laden und einee Zeichnung?

------------------
( ... MfG, benjamin ... )

Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP

Jonapap
Mitglied



Sehen Sie sich das Profil von Jonapap an!   Senden Sie eine Private Message an Jonapap  Schreiben Sie einen Gästebucheintrag für Jonapap

Beiträge: 206
Registriert: 18.08.2006

erstellt am: 23. Apr. 2007 10:36    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat    Unities abgeben: 1 Unity (wenig hilfreich, aber dennoch)2 Unities3 Unities4 Unities5 Unities6 Unities7 Unities8 Unities9 Unities10 Unities Nur für bennyboss 10 Unities + Antwort hilfreich

Netload automatisieren:
1.Debug-Pfad der dll-Datei mit bei den Supportpfaden von Acad eintragen
2.(command "Netload" "Testprojekt") z.B. in die acaddoc.lsp eintragen

Vorlagedatei laden:
In VS unter Debug bei "Command Line Args" folgendes eintragen:
/p "Testprofil" /t "C:\Test.dwg"

------------------
Gruß
Markus

Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP

bennyboss
Mitglied



Sehen Sie sich das Profil von bennyboss an!   Senden Sie eine Private Message an bennyboss  Schreiben Sie einen Gästebucheintrag für bennyboss

Beiträge: 15
Registriert: 07.11.2005

ThinkPad 60, OS: Vista Business, CPU: 1,86 Core 2 Duo, RAM: 2GB, AutoCAD: 2008, VisualStudio2005

erstellt am: 23. Apr. 2007 11:00    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat    Unities abgeben: 1 Unity (wenig hilfreich, aber dennoch)2 Unities3 Unities4 Unities5 Unities6 Unities7 Unities8 Unities9 Unities10 Unities

super! funktioniert wunderbar, danke! 

(ich muss mal AutoCAD User Guide lesen, ich hab garnicht gewusst (und erwartet) dass AC so viele "Command line switches" hat)

und jetzt an die Arbeit, BlockCount als eine DLL-Datei, das wird interresant 

------------------
( ... MfG, benjamin ... )

Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP

bennyboss
Mitglied



Sehen Sie sich das Profil von bennyboss an!   Senden Sie eine Private Message an bennyboss  Schreiben Sie einen Gästebucheintrag für bennyboss

Beiträge: 15
Registriert: 07.11.2005

ThinkPad 60, OS: Vista Business, CPU: 1,86 Core 2 Duo, RAM: 2GB, AutoCAD: 2008, VisualStudio2005

erstellt am: 23. Apr. 2007 17:20    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat    Unities abgeben: 1 Unity (wenig hilfreich, aber dennoch)2 Unities3 Unities4 Unities5 Unities6 Unities7 Unities8 Unities9 Unities10 Unities

klasse! ich muss sagen ich bin begeistert, jetzt braucht die DLL weniger als eine Sekunde um alle Blöcke zu zählen, dagegen die alte die über die COM-Schnitstelle auf AutoCAD zugriff hatte, brauchte jedes mal mehr als eine Minute, manchmal sogar 6 und mehr!

das ist der Haput-Code der nach Blöcken in einer Zeichnung sucht und macht davon eine Liste mit deren Inhalt, es gibt noch mehr Code aber dann wäre das Prinzip unübersichtlich denke ich, also wenn jemand das ganze Funktion braucht dann bitte bei mir melden

vielleicht nutzt der Code jemandem:

Code:

public class BlockCounter
    {
        private Transaction tr;
        private BlockTable bt;

        [Autodesk.AutoCAD.Runtime.CommandMethod("nblocks")]
        public void HelloCommand()
        {
            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;

            tr = doc.TransactionManager.StartTransaction();

            bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
         
            // zu erst suche ich alle BlockDefinitions um zu wissen wie viele das sind um myBlocks-Array mit fester Größe initiieren zu können
            #region get blockNames
            ArrayList blockNames = new ArrayList();
            BlockTableRecord btr;
            foreach (ObjectId tmpBlockId in bt)
            {
                btr = (BlockTableRecord)tr.GetObject(tmpBlockId, OpenMode.ForRead, false);
                if (btr.IsLayout == false)
                {                   
                    blockNames.Add(btr.Name);
                }
            }
            #endregion

            object[,] myBlocks = new object[blockNames.Count, 2]; // block counters

            int i0 = 0;
            ArrayList blockItems; // block contents
            BlockTableRecord blockDef;
            foreach (ObjectId tmpBlockId in bt) // noch mal eine Schleiffe über alle Blöcke
            {
                blockDef = (BlockTableRecord)tr.GetObject(tmpBlockId, OpenMode.ForRead, false);
                if (blockDef.IsLayout == false) // wir wollen keine von den drei default-Blocks
                {
                    blockItems = new ArrayList(); // der Inhalt eines Blocks (wird später benötigt)
                    myBlocks[i0, 0] = blockDef.Name;
                    Entity ent;
                    BlockReference blockRef;
                    foreach (ObjectId blockItem in blockDef)
                    {
                        ent = (Entity)tr.GetObject(blockItem, OpenMode.ForRead, false);
                        // wenn ein Object in dem Block ein BlockRef ist dann such das BlockDef nach mehr
                        if (string.Compare(ent.GetType().Name, "BlockReference") == 0)
                        {
                            blockRef = (BlockReference)ent;
                            blockItems.Add(blockRef.Name);
                            GoDeeper(bt[blockRef.Name], ref blockItems);
                            myBlocks[i0, 1] = blockItems;
                        }                                              
                    }
                    i0 = i0 + 1;
                }
            }
            tr.Commit();
            acadApp.DocumentManager.MdiActiveDocument.Editor.WriteMessage("fertig!");
            acadApp.UpdateScreen();
        }


und die Regkurenz-Funktion

Code:

        private void GoDeeper(ObjectId blockDefId, ref ArrayList blockItems)
        {
            BlockTableRecord blockDef = (BlockTableRecord)tr.GetObject(blockDefId, OpenMode.ForRead, false);
            Entity ent;
            BlockReference blockRef;
            foreach (ObjectId blockItem in blockDef)
            {
                ent = (Entity)tr.GetObject(blockItem, OpenMode.ForRead, false);
                if (string.Compare(ent.GetType().Name, "BlockReference") == 0)
                {
                    blockRef = (BlockReference)ent;
                    blockItems.Add(blockRef.Name);
                    GoDeeper(bt[blockRef.Name], ref blockItems);
                }
            }
        }
} // Class-Ende

------------------
( ... MfG, benjamin ... )

[Diese Nachricht wurde von bennyboss am 23. Apr. 2007 editiert.]

Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP

RoSiNiNo
Mitglied
Konstrukteur


Sehen Sie sich das Profil von RoSiNiNo an!   Senden Sie eine Private Message an RoSiNiNo  Schreiben Sie einen Gästebucheintrag für RoSiNiNo

Beiträge: 1126
Registriert: 09.10.2002

Revit Structure 2011
Acad 2011-deutsch, Express Tools
3ds Max 2011
Win 7-Professional
HP Workstation Z400, 6GB
GeForce GTX 470

erstellt am: 08. Mai. 2007 11:33    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat    Unities abgeben: 1 Unity (wenig hilfreich, aber dennoch)2 Unities3 Unities4 Unities5 Unities6 Unities7 Unities8 Unities9 Unities10 Unities Nur für bennyboss 10 Unities + Antwort hilfreich

Hier vielleicht ein etwas anderer Lösungsansatz, hier muss man allerdings noch alle unnötigen Blöcke ausschließen (Bemaßungen, anonyme Blöcke, etc.).
Code:
        [CommandMethod("TestBlockCount")]
        static public void BlockCountTest()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;
            int i = 0;
            try
            {
                using (Transaction tr = doc.TransactionManager.StartTransaction())
                using (BlockTable bt = (BlockTable)tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead, false))
                {
                    foreach (ObjectId blockId in bt)
                    {
                        using (BlockTableRecord btr = (BlockTableRecord)tr.GetObject(blockId, OpenMode.ForRead, false))
                        {
                            if (btr.IsLayout == false)
                            {
                                ObjectIdCollection IDColl = btr.GetBlockReferenceIds(false, false);
                                i += IDColl.Count;
                            }
                        }
                    }
                    tr.Commit();
                }
                ed.WriteMessage(System.String.Format("\nAnzahl der Blöcke in der Zeichnung: {0}!", i.ToString()));

            }
            catch
            {
                //Mach etwas
            }
            finally
            {
                //Mach nix
            }
        }


------------------
Roland Feletic
PAUSER ZT-GMBH

Acad 2008-deutsch, Express Tools
3ds Max 9
WinXP-Professional
HP Workstation xw4400, 3GB
Quadro FX1500

Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP

Anzeige.:

Anzeige: (Infos zum Werbeplatz >>)

Darstellung des Themas zum Ausdrucken. Bitte dann die Druckfunktion des Browsers verwenden. | Suche nach Beiträgen

nächster neuerer Beitrag | nächster älterer Beitrag
Antwort erstellen


Diesen Beitrag mit Lesezeichen versehen ... | Nach anderen Beiträgen suchen | CAD.de-Newsletter

Administrative Optionen: Beitrag schliessen | Archivieren/Bewegen | Beitrag melden!

Fragen und Anregungen: Kritik-Forum | Neues aus der Community: Community-Forum

(c)2023 CAD.de | Impressum | Datenschutz