Hot News:

Mit Unterstützung durch:

  Foren auf CAD.de (alle Foren)
  AutoCAD ObjectARX und .NET
  Verwendete Objekte wieder freigeben

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:  Verwendete Objekte wieder freigeben (1187 mal gelesen)
veydan
Mitglied



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

Beiträge: 252
Registriert: 29.05.2008

AutoCAD/Mechanical 2009, Inventor 2009

erstellt am: 03. Feb. 2010 14: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

Hallo!
Ich habe folgendes Problem, wenn man in der Zeichnung irgendetwas ändert, sollte ja man die db, ed, layertables usw, was man dann verwendet hat ja wieder .dispose() bzw auf nothing setzen.

Gibt es da eine bestimme Reihenfolge?, oder irgend etwas anderes zu beachten?

Was gibt es beim Dokumentlock alles zu beachten, wann muss der gesetzt werden?
Ich habe den jetzt am anfang meiner Konvertierung gesetzt und ganz am ende (es werden mehrere Funktionen durchlaufen) mache ich

Code:
If tAcadDocLock IsNot Nothing Then tAcadDocLock.Dispose() : tAcadDocLock = Nothing

Muss der vor oder nach der Zeichnungsdatenbank aufgehoben werden, oder ist es egal?

Hier z.b eine Teilfunktion

Code:

  Dim tDocLock As ApplicationServices.DocumentLock = Nothing
        Dim doc As Document = Application.DocumentManager.MdiActiveDocument
        Dim db As Database = doc.Database
        Dim targetlayerobjectid As ObjectId = Nothing
        Dim tr As Transaction = db.TransactionManager.StartTransaction()
        Dim ed As EditorInput.Editor = doc.Editor
        Dim lt As LayerTable = Nothing

try
'Code
Catch ex As Exception
            MsgBox(ex.Message & vbNewLine & ex.StackTrace)
        Finally
            If tr IsNot Nothing Then tr.Dispose() : tr = Nothing
            If ltr IsNot Nothing Then ltr.Dispose() : ltr = Nothing
            If lt IsNot Nothing Then lt.Dispose() : lt = Nothing
            If db IsNot Nothing Then db.CloseInput(True) : db.Dispose() : db = Nothing
            If ed IsNot Nothing Then ed = Nothing
        End Try


Im speziellen geht es mir darum, dass ich Elemente von einem auf einen anderen Layer verschiebe, während der konvertierung habe ich mir ein paar Messageboxen ausgeben lassen, und da sieht man im Hintergrund schon wie sich die Linien anders Färben.
ist die Konvertierung fertig, ist aber alles wieder schwarz...
Rufe ich dann den Layer Manager mittels "la" Befehl auf, bekomme ich einen Systemfehler udn Autocad stürzt ab, daher die Vermutung, dass ich da beim freigeben was falsch mache.

mfg

[Diese Nachricht wurde von veydan am 03. Feb. 2010 editiert.]

[Diese Nachricht wurde von veydan am 03. Feb. 2010 editiert.]

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


Ex-Mitglied

erstellt am: 03. Feb. 2010 18:00    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat

Hi,

>> sollte ja man die db, ed, layertables usw, was man dann verwendet hat
>> ja wieder .dispose() bzw auf nothing setzen

VORSICHT!
.Dispose soll (meistens darf) nur verwendet werden, wenn Du eine Instanz erstellst, nicht wenn Du eine Verbindung zu einer bestehenden Instanz erstellst.

Erstellst Du einen Text mit New DbText, dann hast Du die Instanz erstellt und solltest diese auch mit .Dispose wieder freigeben (wenn diese nicht über TransAction der Datenbank hinzugefügt wurde).

Wenn Du Dich mit einer aktuell geöffneten Zeichnungsdatenbank verbindest, dann lass bitte das Freigeben des Speichers dem AutoCAD über, in diesem Fall erstellst Du ja keine Instanz, sondern AutoCAD hat beim Öffnen der DWG die Instanz erstellt, muss diese daher auch selbst mit wieder freigeben.


>> Was gibt es beim Dokumentlock alles zu beachten, wann muss der gesetzt werden?

Das Locking der Datenbank wird benötigt, damit während des Ablauf Deines Programms weder der Anwender noch eine andere Applikation 'dazwischenfunken' kann.
Startest Du einen Befehl, dann kannst Du bereits in den Attributen der Befehlsdefinition angeben, ob dieser Befehl das Document sperrt (exklusiv in die Hand nimmt). Startest Du aber eine Sub/Function, die nicht als AutoCAD-Befehl registriert ist, z.B. aus eigener Form heraus, dann musst Du vor Änderung von Elementen das Sperren per DocLock aktivieren.
Hast Du aber eine Datenbank nicht in den Editor geladen, dann liegt es an Dir, wie Du mit dieser Zeichnung umgehst.


>> Hier z.b eine Teilfunktion .....

In Deinem Code kommt ja gar kein DocumentLocking vor?
Grundsätzlich ist .Dispose von Objekten in umgekehrter Reihenfolge zur Erstellung der Objekte zu setzten, also erst erstellen von DocLock, dann TransAction, dann Objektbearbeitung, danach TransAction.Dispose und nachfolgend DocLock.Dispose.

HTH, - alfred -

------------------
www.hollaus.at

veydan
Mitglied



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

Beiträge: 252
Registriert: 29.05.2008

AutoCAD/Mechanical 2009, Inventor 2009

erstellt am: 03. Feb. 2010 18:15    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

Zitat:
Original erstellt von a.n.:
>> sollte ja man die db, ed, layertables usw, was man dann verwendet hat
>> ja wieder .dispose() bzw auf nothing setzen

VORSICHT!
.Dispose soll (meistens darf) nur verwendet werden, wenn Du eine Instanz erstellst, nicht wenn Du eine Verbindung zu einer bestehenden Instanz erstellst.

Erstellst Du einen Text mit New DbText, dann hast Du die Instanz erstellt und solltest diese auch mit .Dispose wieder freigeben (wenn diese nicht über TransAction der Datenbank hinzugefügt wurde).



ok, also wenn ich z.B einen Layer erstelle und den der Datenbank hinzufüge, ist das dispose hinfällig,wenn ich den nicht hinzufüge ist er zum disposen, habe ich das richtig verstanden?

Zitat:

>> Hier z.b eine Teilfunktion .....

In Deinem Code kommt ja gar kein DocumentLocking vor?
Grundsätzlich ist .Dispose von Objekten in umgekehrter Reihenfolge zur Erstellung der Objekte zu setzten, also erst erstellen von DocLock, dann TransAction, dann Objektbearbeitung, danach TransAction.Dispose und nachfolgend DocLock.Dispose.



Bei diesem Funktionsaufbau kommt nach dem Konvertieren eine Systemfehler und Autocad stürzt ab.
Dass ist irgendwie willkürlich, einmal wenn ich dann den Layermanager aufrufe, einmal wenn ich einfach noch warte und in der Zeichnung rumklicke, irgendwie kein Muster...
Gibt es da Hinweise, was die Abstürze verursachen kann? die Fehlernummer ist ja nicht wirklich aussagekräftig.


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


Ex-Mitglied

erstellt am: 03. Feb. 2010 18:38    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat

Hi,

>> ok, also wenn ich z.B einen Layer erstelle und den der Datenbank hinzufüge,
>> ist das dispose hinfällig,wenn ich den nicht hinzufüge ist er zum disposen,
>> habe ich das richtig verstanden?

Genau so! 


>> Bei diesem Funktionsaufbau kommt nach dem Konvertieren eine Systemfehler und Autocad stürzt ab

Da müsste ich den ganzen Code sehen, was dazwischen passiert.
I.d.R. können wir mit den Fehlernummern nur dann etwas anfangen, wenn wir dieses in Google eingeben, manchmal kommt da was, aber Doku würde ich keine dazu kennen.

- alfred -

------------------
www.hollaus.at

veydan
Mitglied



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

Beiträge: 252
Registriert: 29.05.2008

AutoCAD/Mechanical 2009, Inventor 2009

erstellt am: 03. Feb. 2010 18:47    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

ok, hier mal die 2 funktionen.
Jetzt bekam ich z.b die Meldung "Error handler re-entered exiting now"

Code:
Public Shared Function CreateOrChangeLayer(ByVal Layername As String, ByVal colorindex As Short, ByVal lineweight As Integer, ByVal linetype As String, ByVal hidden As String) As Integer
       ---Code---
    End Function
    Public Shared Function ChangeEntitiesLayer(ByVal SourceLayer As String, ByVal TargetLayer As String)
       ---Code---
    End Function

mfg

Edit:Absprache nach PM

[Diese Nachricht wurde von veydan am 03. Feb. 2010 editiert.]

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


Ex-Mitglied

erstellt am: 03. Feb. 2010 19:09    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat

Hi,

ich hab jetzt den Code nicht laufen lassen (Begründung siehe PM), aber ich sehe:

A) im ersten/langen Else-Bereich

Code:
ltr = New LayerTableRecord
ltr = CType(tr.GetObject(lt.Item(Layername), OpenMode.ForWrite, True, True), LayerTableRecord)

Hier hast Du schon mal ein Beispiel, wo Du Speicher genommen, aber nicht mehr freigegeben hast. Zuerst erstellst Du eine neue Instanz eines LTR, in der nächsten Zeile holst Du Dir eine bestehende Referenz aus der Zeichnung. Die erste Zeile ist damit hinfällig, hat sich aber Speicher geholt, der nicht mehr ordnungsgemäß freigegeben wurde.

B) Du öffnest oft mit 'ForWrite', wo Du es nicht brauchst. Das macht Dein Programm langsamer, weiters speicherintensiver und last-but-not-least instabiler. Wenn Du z.B. den LTR durchgehst, dann mach mal öffnen nur zum Lesen und erst, wenn Du weisst, dass Du Werte ändern musst, dann ein UpgradeOpen.


C) Wenn Du eine Table durchgehst (Layer-, Linetypes-, Blocks, ....), dann solltest Du auch wissen, dass .Has Dir auch gelöschte Elemente retourniert. Z.B. Du legst einen Layer XXX an, dann löscht Du diesen, legst erneut einen Layer XXX (also gleicher Name) an, dann kann es durchaus passieren, dass die mit .Has einen Record erhältst, dessen Eigenschaft .IsEraed auf TRUE steht, und es noch einen weitern gibt!

D) Return 0 ....steigt Dir aus der Function aus und kommt gar nicht zu den nächsten Statements, da es in der Schachtelung Try...End Try ist, befindest Du Dich auf ziemlichem Glatteis, wie der Stack da ordnungsgemäß zurückfindet. Ein Return gibts bei mir immer nur als letzte Zeile einer Function.

E) In ChangeEntitiesLayer sehe ich kein TransAction.Dispose!

- alfred -

------------------
www.hollaus.at

veydan
Mitglied



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

Beiträge: 252
Registriert: 29.05.2008

AutoCAD/Mechanical 2009, Inventor 2009

erstellt am: 03. Feb. 2010 20: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

A: danke dass habe ich wirklich übersehen, der Tag war einfach zu lange...

B:
 

Zitat:

Du öffnest oft mit 'ForWrite', wo Du es nicht brauchst. Das macht Dein Programm langsamer, weiters speicherintensiver und last-but-not-least instabiler. Wenn Du z.B. den LTR durchgehst, dann mach mal öffnen nur zum Lesen und erst, wenn Du weisst, dass Du Werte ändern musst, dann ein UpgradeOpen.


Gehe ich richtig in der Annahme, dass UpgradeOpen ein Objekt von Read auf Write setzt und DowngradeOpen von Write auf Read?

C:
 

Zitat:

Wenn Du eine Table durchgehst (Layer-, Linetypes-, Blocks, ....), dann solltest Du auch wissen, dass .Has Dir auch gelöschte Elemente retourniert. Z.B. Du legst einen Layer XXX an, dann löscht Du diesen, legst erneut einen Layer XXX (also gleicher Name) an, dann kann es durchaus passieren, dass die mit .Has einen Record erhältst, dessen Eigenschaft .IsEraed auf TRUE steht, und es noch einen weitern gibt!


Ok, also auf IsErased abprüfen, wann werden solche IsErased = True Einträge entfernt? beim Purge?

E:ebenfalls übersehen...


wie sieht es mit folgender Zeile aus:
ent = CType(tr.GetObject(id, OpenMode.ForWrite, True, True), Entity)
wenn ich die Variable ent in einer Schleife immer wieder neu zuweise
dann einen Wert ändere und nach der Schleife tr.commit sage (siehe code)
ent muss dann nicht disposed werden?

danke
mfg

[Diese Nachricht wurde von veydan am 03. Feb. 2010 editiert.]

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


Ex-Mitglied

erstellt am: 03. Feb. 2010 20:30    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat

Hi,

>> Gehe ich richtig in der Annahme, dass UpgradeOpen ein Objekt von Read auf Write setzt
>> und DowngradeOpen von Write auf Read?

UpgradeOpen oder ein erneutes TrAct.GetObject mit 'ForWrite' öffnet zum Schreiben ==> JA
DowngradeOpen verwende ich nicht, da ich nicht sicher bin, wie dies mit TrAct.Commit zusammenspielt, für mich ist das undefiniert und daher mach ich das nicht.


>> wann werden solche IsErased = True Einträge entfernt? beim Purge?

Purge sollte es clean machen, nur darauf kannst Du Dich in der Applikation nicht verlassen (dass der Anwender nach Layer-löschen auch ein _Purge macht).


>> wenn ich die Variable ent in einer Schleife immer wieder neu zuweise

Nein, wenn Du Dir ein bestehendes Element holst, dann kein .Dispose. Der Regelfall lautet,
wenn Du New ... verwendest, dann .Dispose,
wenn Du TrAct.GetObject verwendest, dann kein .Dispose

HTH, - alfred -

------------------
www.hollaus.at

veydan
Mitglied



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

Beiträge: 252
Registriert: 29.05.2008

AutoCAD/Mechanical 2009, Inventor 2009

erstellt am: 03. Feb. 2010 21:35    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

ist es eigentlich egal, wo man die Transaction disposed? Im Using, nach dem Using,...

wenn ich neue layer erzeuge, sehe ich sie kurz in der drop down liste, im Layermanager verschwinden sie dann wieder.

Hier das erzeugen:


lt.Add(ltr)
tr.AddNewlyCreatedDBObject(ltr, True)
tr.Commit()

es ist aber alles nötige vorhanden...

mfg

edit:
so ich habe glaube ich einen Teil der Lösung gefunden.
Meine Funktionen mit der Autocadfunktionsklasse dürfen nicht Shared sein.

aber was mir jetzt noch aufgefallen ist, nach der konvertierung, wenn ich Strg + s drücke zum speichern sagt autocad:
In Dokument ~Dokumentpfad~ wird gerade ein Befehl ausgeführt. Drücken Sie zum Abbruch die Eingabetaste

wurde in so einem fall auch nicht alles richtig freigegeben?

[Diese Nachricht wurde von veydan am 04. Feb. 2010 editiert.]

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


Ex-Mitglied

erstellt am: 04. Feb. 2010 16:32    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat

Hi,

>> In Dokument ~Dokumentpfad~ wird gerade ein Befehl ausgeführt

Ist ein (fast) eindeutiges Zeichen dafür, dass das DocumentLock noch nicht aufgehoben ist.
Das könnte auch erklären, warum Layermanger-Inhalt nicht mit den vermuteten Inhalten zusammenpasst.

- alfred -

------------------
www.hollaus.at

veydan
Mitglied



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

Beiträge: 252
Registriert: 29.05.2008

AutoCAD/Mechanical 2009, Inventor 2009

erstellt am: 04. Feb. 2010 18:34    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

so, jetzt gehts wirklich eins kleingedruckte...

wie muss man bei dieser Schleife das dispose setzen

Code:

myDwg = Application.DocumentManager.MdiActiveDocument
tAcadDocLock = myDwg.LockDocument
myTransMan = myDwg.TransactionManager
myTrans = myTransMan.StartTransaction
Dim myAttColl As DatabaseServices.AttributeCollection = Nothing
Dim myEnt As DatabaseServices.Entity = Nothing
Dim myBTREnum As BlockTableRecordEnumerator = Nothing
myAttColl = myBlockRef.AttributeCollection
myBTREnum = myBlockDef.GetEnumerator
While myBTREnum.MoveNext
  myEnt = myBTREnum.Current.GetObject(OpenMode.ForWrite)
  If TypeOf myEnt Is DatabaseServices.AttributeDefinition Then
    Dim myAttDef As DatabaseServices.AttributeDefinition = myEnt
    Dim myAttRef As New DatabaseServices.AttributeReference
    myAttRef.SetAttributeFromBlock(myAttDef, myBlockRef.BlockTransform)
    myAttColl.AppendAttribute(myAttRef)
    myTrans.AddNewlyCreatedDBObject(myAttRef, True)
    myAttRef.Dispose()
    myAttRef = Nothing
  End If
End While

myTrans.Commit()

myTrans.dispose()


würden da jetzt alles korrekt ablaufen, wernn das .dispose noch in der schleife ist, vor dem Transaction.Commit?

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


Ex-Mitglied

erstellt am: 04. Feb. 2010 18:43    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat

Uii,

Du mischt 2 Modelle, wie auf Entities hingegriffen wird. Die Open-Methode, welche keine TransAction benötigt (siehe myBTREnum.Current.GetObject(OpenMode.ForWrite)) und die TransAction-basierende Methode (siehe myTrans.AddNewlyCreatedDBObject(myAttRef, True)).

Zu Dispose: Da Du das Attribut der Datenbank hinzufügst, darf dieses:
myAttRef.Dispose()
gar nicht mehr aufgerufen werden. Du 'zerstörst' eine Objektstruktur, die Du zuvor der Datenbank hinzugefügt hast.

HTH, - alfred -

------------------
www.hollaus.at

veydan
Mitglied



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

Beiträge: 252
Registriert: 29.05.2008

AutoCAD/Mechanical 2009, Inventor 2009

erstellt am: 04. Feb. 2010 18:49    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

stimmt, hast du ja ein paar Beiträge oben schon gesagt...
Da fehlt mir noch das Auge zum Detail...

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