<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Autocad crash when transaction ends in .NET Forum</title>
    <link>https://forums.autodesk.com/t5/net-forum/autocad-crash-when-transaction-ends/m-p/9465814#M19761</link>
    <description>&lt;P&gt;Hi,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN class="tlid-translation translation"&gt;&lt;SPAN title=""&gt;I don't quite understand the relationship between erasing an object and then canceling the operation and the posted code.&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN title=""&gt;Regarding the posted code, the 'findBlockRecord' method should not return an instance of BlockTableRecord (or of any DBOject) that has been opened in a disposed transaction (the BlockTableRecord has also been disposed), the method should return an ObjectId.&lt;/SPAN&gt; &lt;SPAN title=""&gt;And the 'hasXRecord' method does not need to start a new nested transaction, we can very well pass the top transaction as an argument to it.&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="csharp"&gt;        static bool HasXRecord(Transaction tr, DBObject dbObject, string key, object dataValue)
        {
            if (dbObject.ExtensionDictionary.IsNull)
                return false;
            var xDict = (DBDictionary)dbObject.ExtensionDictionary.GetObject(OpenMode.ForRead);
            if (!xDict.Contains(key))
                return false;
            var xrec = (Xrecord)xDict.GetAt(key).GetObject(OpenMode.ForRead);
            return xrec.Data.AsArray()[0].Value.Equals(dataValue);
        }

        static ObjectId FindBlockRecord(Database db, string key, object dataValue)
        {
            using (var tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                return bt.Cast&amp;lt;ObjectId&amp;gt;()
                    .FirstOrDefault(id =&amp;gt; HasXRecord(tr, tr.GetObject(id, OpenMode.ForRead), key, dataValue));
            }
        }&lt;/LI-CODE&gt;</description>
    <pubDate>Thu, 23 Apr 2020 18:56:42 GMT</pubDate>
    <dc:creator>_gile</dc:creator>
    <dc:date>2020-04-23T18:56:42Z</dc:date>
    <item>
      <title>Autocad crash when transaction ends</title>
      <link>https://forums.autodesk.com/t5/net-forum/autocad-crash-when-transaction-ends/m-p/9465358#M19760</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I would like to create a dynamic legends so I wrote some handler for:&lt;/P&gt;&lt;P&gt;Database.ObjectAppended&lt;BR /&gt;Database.ObjectErased&lt;BR /&gt;Database.ObjectModified&lt;BR /&gt;Database.ObjectReappended&lt;BR /&gt;Database.ObjectUnappended&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;In my test case I erase an object (manually) (so I pass in Database.ObjectErased ) and do an undo then&lt;/P&gt;&lt;P&gt;I pass in Database.ObjectErased&amp;nbsp; for the second time.&lt;/P&gt;&lt;P&gt;My functions are called:&lt;/P&gt;&lt;LI-CODE lang="general"&gt;/// &amp;lt;summary&amp;gt;
        /// Test si le xrecord existe
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="objid"&amp;gt;Objet contenant le xrecord&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="tag"&amp;gt;tag du xrecord&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="xData"&amp;gt;data du xrecord&amp;lt;/param&amp;gt;
        /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
        static protected internal bool hasXRecord(ObjectId objid, string tag, object xData)
        {
            bool bRet = false;
            Document doc = Application.DocumentManager.MdiActiveDocument;
            using (Transaction acTrans = doc.TransactionManager.StartTransaction())
            {
                DBObject pObj = objid.GetObject(OpenMode.ForRead);
                if (!pObj.ExtensionDictionary.IsNull)
                {
                    DBDictionary xDict = pObj.ExtensionDictionary.GetObject(OpenMode.ForRead) as DBDictionary;
                    if(xDict.Contains(tag))
                    {
                        Xrecord rec = xDict.GetAt(tag).GetObject(OpenMode.ForRead) as Xrecord;
                        bRet = rec.Data.AsArray()[0].Value.Equals(xData);
                    }
                }
            }
            return bRet;
        }

        /// &amp;lt;summary&amp;gt;
        /// Recherche bloc avec un xrecord spécifique
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="tag"&amp;gt;tag xrecord&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="xData"&amp;gt;valeur xrecord&amp;lt;/param&amp;gt;
        /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
        static protected internal BlockTableRecord findBlockRecord(string tag, object xData)
        {
            BlockTableRecord bloc = null;
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            using (Transaction acTrans = doc.TransactionManager.StartTransaction())
            {
                BlockTable blocTable = db.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
                foreach(ObjectId blocId in blocTable)
                {
                    if(hasXRecord(blocId, tag, xData))
                    {
                        bloc = blocId.GetObject(OpenMode.ForRead) as BlockTableRecord;
                        break;
                    }
                }
            }
            return bloc;
        }&lt;/LI-CODE&gt;&lt;P&gt;for each Database.ObjectErased but the second Database.ObjectErased (= with undo) cause a kind of deadlock in the end of transaction in function hasXRecord.&lt;/P&gt;&lt;P&gt;I have to use transaction if I want open the objectid.&lt;/P&gt;&lt;P&gt;It'is a BUG or what I'm doing wrong?&lt;/P&gt;&lt;P&gt;thanks&lt;/P&gt;</description>
      <pubDate>Thu, 23 Apr 2020 15:56:14 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/autocad-crash-when-transaction-ends/m-p/9465358#M19760</guid>
      <dc:creator>Anonymous</dc:creator>
      <dc:date>2020-04-23T15:56:14Z</dc:date>
    </item>
    <item>
      <title>Re: Autocad crash when transaction ends</title>
      <link>https://forums.autodesk.com/t5/net-forum/autocad-crash-when-transaction-ends/m-p/9465814#M19761</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN class="tlid-translation translation"&gt;&lt;SPAN title=""&gt;I don't quite understand the relationship between erasing an object and then canceling the operation and the posted code.&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN title=""&gt;Regarding the posted code, the 'findBlockRecord' method should not return an instance of BlockTableRecord (or of any DBOject) that has been opened in a disposed transaction (the BlockTableRecord has also been disposed), the method should return an ObjectId.&lt;/SPAN&gt; &lt;SPAN title=""&gt;And the 'hasXRecord' method does not need to start a new nested transaction, we can very well pass the top transaction as an argument to it.&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="csharp"&gt;        static bool HasXRecord(Transaction tr, DBObject dbObject, string key, object dataValue)
        {
            if (dbObject.ExtensionDictionary.IsNull)
                return false;
            var xDict = (DBDictionary)dbObject.ExtensionDictionary.GetObject(OpenMode.ForRead);
            if (!xDict.Contains(key))
                return false;
            var xrec = (Xrecord)xDict.GetAt(key).GetObject(OpenMode.ForRead);
            return xrec.Data.AsArray()[0].Value.Equals(dataValue);
        }

        static ObjectId FindBlockRecord(Database db, string key, object dataValue)
        {
            using (var tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                return bt.Cast&amp;lt;ObjectId&amp;gt;()
                    .FirstOrDefault(id =&amp;gt; HasXRecord(tr, tr.GetObject(id, OpenMode.ForRead), key, dataValue));
            }
        }&lt;/LI-CODE&gt;</description>
      <pubDate>Thu, 23 Apr 2020 18:56:42 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/autocad-crash-when-transaction-ends/m-p/9465814#M19761</guid>
      <dc:creator>_gile</dc:creator>
      <dc:date>2020-04-23T18:56:42Z</dc:date>
    </item>
    <item>
      <title>Re: Autocad crash when transaction ends</title>
      <link>https://forums.autodesk.com/t5/net-forum/autocad-crash-when-transaction-ends/m-p/9471436#M19762</link>
      <description>&lt;P&gt;&lt;SPAN class="tlid-translation translation"&gt;&lt;SPAN&gt;"I don't quite understand the relationship between erasing an object and then canceling the operation and the posted code"&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN class="tlid-translation translation"&gt;&lt;SPAN&gt;Delete object and undo deletetion both call Database.ObjectErased. In fact is not a problem.&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;SPAN class="tlid-translation translation"&gt;&lt;SPAN&gt;"the method should return an ObjectId"&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN class="tlid-translation translation"&gt;&lt;SPAN&gt;I agree and I correct my method (even it's&amp;nbsp; weird to use transactions to open object but I have to).&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN class="tlid-translation translation"&gt;&lt;SPAN&gt;But the crash already exists.&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;SPAN class="tlid-translation translation"&gt;&lt;SPAN&gt;I can avoid this crash by calling an legend update command via sendStringToExecute (same code is executed).&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN class="tlid-translation translation"&gt;&lt;SPAN&gt;BUT I have another problem if legend update command is executed my selection is automatically cleared.&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 26 Apr 2020 16:42:23 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/autocad-crash-when-transaction-ends/m-p/9471436#M19762</guid>
      <dc:creator>Anonymous</dc:creator>
      <dc:date>2020-04-26T16:42:23Z</dc:date>
    </item>
    <item>
      <title>Re: Autocad crash when transaction ends</title>
      <link>https://forums.autodesk.com/t5/net-forum/autocad-crash-when-transaction-ends/m-p/9471505#M19763</link>
      <description>&lt;P&gt;Sorry, I still do not understand your issue (maybe due to my English).&lt;/P&gt;
&lt;P&gt;You should post a usable code&amp;nbsp; and a detailed description of the circonsatances the error occurs so that we can reproduce it.&lt;/P&gt;</description>
      <pubDate>Sun, 26 Apr 2020 17:08:49 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/autocad-crash-when-transaction-ends/m-p/9471505#M19763</guid>
      <dc:creator>_gile</dc:creator>
      <dc:date>2020-04-26T17:08:49Z</dc:date>
    </item>
    <item>
      <title>Re: Autocad crash when transaction ends</title>
      <link>https://forums.autodesk.com/t5/net-forum/autocad-crash-when-transaction-ends/m-p/9471715#M19764</link>
      <description>&lt;P&gt;My english is also horrible.&lt;/P&gt;&lt;P&gt;I think my problem is due to executed commands:&lt;/P&gt;&lt;P&gt;The command undo is still running when my code is executed.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I finally avoid&amp;nbsp; the crash and the selection clearing problem by this code:&lt;/P&gt;&lt;LI-CODE lang="csharp"&gt;static void legendCallback(object sender, ObjectErasedEventArgs e)
        {
            DBObject objTeated = e.DBObject;
            if (objTeated != null)
            {
                if (!PICLegendZoneCmd.UPDATE_MUTEX)// mutex MAJ
                {
                    Document doc = Application.DocumentManager.MdiActiveDocument;
                    if ((objTeated.GetType() == typeof(MgPICZone)) || (objTeated.GetType() == typeof(MgPICWay)))
                    {
                        string names = Application.GetSystemVariable("CMDNAMES") as string;
                        if (names.Length &amp;gt; 0)
                        {
                            PICLegendZoneCmd.UPDATE_MUTEX = true;
                            // moyen de contourner un crash (BUG AUTOCAD!?) qd fin transaction =&amp;gt; CRADO
                            Application.DocumentManager.MdiActiveDocument.SendStringToExecute("PICUpdateLegendZone\n", true, false, true);
                        }
                        else
                        {
                            // pas de commande ?= pas de crash mais lancer une commande d'update ou plus généralement une commande
                            // effacera la sélection à la fin
                            PICLegendZoneCmd.updateLegendZone();
                        }
                    }
                }
            }
        }&lt;/LI-CODE&gt;&lt;LI-CODE lang="csharp"&gt;/// &amp;lt;summary&amp;gt;
        /// Commande de mise à jour des légendes de zone
        /// &amp;lt;/summary&amp;gt;
        [CommandMethod("PIC", "PICUpdateLegendZone", "PICUpdateLegendZoneLocal", CommandFlags.Transparent | CommandFlags.UsePickSet | 
            CommandFlags.NoUndoMarker | CommandFlags.NoInferConstraint)]
        public void updateLegendZoneCmd()
        {
            PICLegendZoneCmd.UPDATE_MUTEX = false;
            PICLegendZoneCmd.updateLegendZone();
        }&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 26 Apr 2020 19:26:16 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/autocad-crash-when-transaction-ends/m-p/9471715#M19764</guid>
      <dc:creator>Anonymous</dc:creator>
      <dc:date>2020-04-26T19:26:16Z</dc:date>
    </item>
  </channel>
</rss>

