<?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 : Seeking Advice to Better Routine in .NET Forum</title>
    <link>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3782293#M51070</link>
    <description>&lt;P&gt;Hi,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;While you're doing the same thing for both blocks (excepted the prompt message) you can factorize these statements in a private method.&lt;/P&gt;&lt;P&gt;To avoid starting a transaction at each selection, you'd embed the while loop within the transaction.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;        [CommandMethod("BP")]
        public void BPosition()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            try
            {
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    while (true)
                    {
                        if (!GetBlockInfos(ed, "\nSelect first block: "))
                            break;
                        if (!GetBlockInfos(ed, "\nSelect second block: "))
                            break;
                    }
                    tr.Commit();
                }
            }
            catch (System.Exception e)
            {
                Application.ShowAlertDialog(String.Format("You Failed Horribly :P\n{0}", e.Message));
            }
        }

        private bool GetBlockInfos(Editor ed, String message)
        {
            PromptEntityOptions peo = new PromptEntityOptions(message);
            peo.SetRejectMessage("\nMust be a block.");
            peo.AddAllowedClass(typeof(BlockReference), false);
            PromptEntityResult per = ed.GetEntity(peo);
            if (per.Status != PromptStatus.OK)
                return false;
            BlockReference br = (BlockReference)per.ObjectId.GetObject(OpenMode.ForRead);
            ed.WriteMessage("\n{0}, Position: {1}", br.Name, br.Position);
            return true;
        }&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;You can also avoid starting a transaction (there's nothing to undo) using the ObjectId.Open() method which have to be considered as "for advanced use only." rather than "obsolete".&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;        [CommandMethod("BP")]
        public void BPosition()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            try
            {
                while (true)
                {
                    if (!GetBlockInfos(ed, "\nSelect first block: "))
                        break;
                    if (!GetBlockInfos(ed, "\nSelect second block: "))
                        break;
                }
            }
            catch (System.Exception e)
            {
                Application.ShowAlertDialog(String.Format("You Failed Horribly :P\n{0}", e.Message));
            }
        }

        private bool GetBlockInfos(Editor ed, String message)
        {
            PromptEntityOptions peo = new PromptEntityOptions(message);
            peo.SetRejectMessage("\nMust be a block.");
            peo.AddAllowedClass(typeof(BlockReference), false);
            PromptEntityResult per = ed.GetEntity(peo);
            if (per.Status != PromptStatus.OK)
                return false;
            using (BlockReference br = (BlockReference)per.ObjectId.Open(OpenMode.ForRead))
            {
                ed.WriteMessage("\n{0}, Position: {1}", br.Name, br.Position);
            }
            return true;
        }&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Sat, 16 Feb 2013 09:15:57 GMT</pubDate>
    <dc:creator>_gile</dc:creator>
    <dc:date>2013-02-16T09:15:57Z</dc:date>
    <item>
      <title>Seeking Advice to Better Routine</title>
      <link>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3782287#M51069</link>
      <description>&lt;P&gt;If you're willing, please offer advice on how to make this routine better. Thanks!&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;//get position of two blocks

namespace BlockPosition
{
    public class DraftingTools
    {
        [CommandMethod("BP")]
        public void BPosition()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;


            try
            {
                while (true)
                {
                    PromptEntityOptions peo = new PromptEntityOptions("\nSelect first block:");
                    peo.SetRejectMessage("\nMust be a block.");
                    peo.AddAllowedClass(typeof(BlockReference), false);
                    PromptEntityResult psr = ed.GetEntity(peo);
                    if (psr.Status != PromptStatus.OK)
                        return;

                    using (Transaction tr = db.TransactionManager.StartTransaction())
                    {
                        ObjectId brId = psr.ObjectId;

                        // Open the block reference
                        BlockReference br = (BlockReference)tr.GetObject(brId, OpenMode.ForRead);


                        var att1 = br.Position;
                        ed.WriteMessage("\n{0}, Position: {1}", br.Name, att1);

                    }

                    PromptEntityOptions peo2 = new PromptEntityOptions("\nSelect second block:");
                    peo2.SetRejectMessage("\nMust be a block.");
                    peo2.AddAllowedClass(typeof(BlockReference), false);
                    PromptEntityResult psr2 = ed.GetEntity(peo2);
                    if (psr2.Status != PromptStatus.OK)
                        return;

                    using (Transaction tr = db.TransactionManager.StartTransaction())
                    {
                        ObjectId brId2 = psr2.ObjectId;

                        // Open the block reference
                        BlockReference br2 = (BlockReference)tr.GetObject(brId2, OpenMode.ForRead);

                        var att2 = br2.Position;
                        ed.WriteMessage("\n{0}, Position: {1}", br2.Name, att2);
                    }
                }
            }
            catch (System.Exception e)
            { Application.ShowAlertDialog(String.Format("You Failed Horribly :P\n{0}", e.Message)); } 
        }

    }
}&lt;/PRE&gt;</description>
      <pubDate>Sat, 16 Feb 2013 08:32:33 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3782287#M51069</guid>
      <dc:creator>brianchapmandesign</dc:creator>
      <dc:date>2013-02-16T08:32:33Z</dc:date>
    </item>
    <item>
      <title>Re : Seeking Advice to Better Routine</title>
      <link>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3782293#M51070</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;While you're doing the same thing for both blocks (excepted the prompt message) you can factorize these statements in a private method.&lt;/P&gt;&lt;P&gt;To avoid starting a transaction at each selection, you'd embed the while loop within the transaction.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;        [CommandMethod("BP")]
        public void BPosition()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            try
            {
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    while (true)
                    {
                        if (!GetBlockInfos(ed, "\nSelect first block: "))
                            break;
                        if (!GetBlockInfos(ed, "\nSelect second block: "))
                            break;
                    }
                    tr.Commit();
                }
            }
            catch (System.Exception e)
            {
                Application.ShowAlertDialog(String.Format("You Failed Horribly :P\n{0}", e.Message));
            }
        }

        private bool GetBlockInfos(Editor ed, String message)
        {
            PromptEntityOptions peo = new PromptEntityOptions(message);
            peo.SetRejectMessage("\nMust be a block.");
            peo.AddAllowedClass(typeof(BlockReference), false);
            PromptEntityResult per = ed.GetEntity(peo);
            if (per.Status != PromptStatus.OK)
                return false;
            BlockReference br = (BlockReference)per.ObjectId.GetObject(OpenMode.ForRead);
            ed.WriteMessage("\n{0}, Position: {1}", br.Name, br.Position);
            return true;
        }&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;You can also avoid starting a transaction (there's nothing to undo) using the ObjectId.Open() method which have to be considered as "for advanced use only." rather than "obsolete".&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;        [CommandMethod("BP")]
        public void BPosition()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            try
            {
                while (true)
                {
                    if (!GetBlockInfos(ed, "\nSelect first block: "))
                        break;
                    if (!GetBlockInfos(ed, "\nSelect second block: "))
                        break;
                }
            }
            catch (System.Exception e)
            {
                Application.ShowAlertDialog(String.Format("You Failed Horribly :P\n{0}", e.Message));
            }
        }

        private bool GetBlockInfos(Editor ed, String message)
        {
            PromptEntityOptions peo = new PromptEntityOptions(message);
            peo.SetRejectMessage("\nMust be a block.");
            peo.AddAllowedClass(typeof(BlockReference), false);
            PromptEntityResult per = ed.GetEntity(peo);
            if (per.Status != PromptStatus.OK)
                return false;
            using (BlockReference br = (BlockReference)per.ObjectId.Open(OpenMode.ForRead))
            {
                ed.WriteMessage("\n{0}, Position: {1}", br.Name, br.Position);
            }
            return true;
        }&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 16 Feb 2013 09:15:57 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3782293#M51070</guid>
      <dc:creator>_gile</dc:creator>
      <dc:date>2013-02-16T09:15:57Z</dc:date>
    </item>
    <item>
      <title>Re : Seeking Advice to Better Routine</title>
      <link>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3782663#M51073</link>
      <description>&lt;P&gt;Merci Gilles, thorough, helpful. I'll use it to continue learning.&lt;/P&gt;</description>
      <pubDate>Sun, 17 Feb 2013 10:27:31 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3782663#M51073</guid>
      <dc:creator>brianchapmandesign</dc:creator>
      <dc:date>2013-02-17T10:27:31Z</dc:date>
    </item>
    <item>
      <title>Re : Seeking Advice to Better Routine</title>
      <link>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3786993#M51074</link>
      <description>&lt;P&gt;I modified the code to do what it was actually intended to do. I still have to look at the better approaches you gave me though, I'm not sure they are possible in my specific scenerio; course I am a noob, and just learning C# now.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;namespace BCCGRSCOMMAND
{
    public class DraftingTools
    {
        [CommandMethod("BCC:GRS")]
        public void BCCGRS()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            try
            {
                while (true)
                {
                    PromptEntityOptions peo = new PromptEntityOptions("\nSelect first block:");
                    peo.SetRejectMessage("\nMust be a block.");
                    peo.AddAllowedClass(typeof(BlockReference), false);
                    PromptEntityResult psr = ed.GetEntity(peo);
                    if (psr.Status != PromptStatus.OK)
                        return;

                    PromptEntityOptions peo2 = new PromptEntityOptions("\nSelect second block:");
                    peo2.SetRejectMessage("\nMust be a block.");
                    peo2.AddAllowedClass(typeof(BlockReference), false);
                    PromptEntityResult psr2 = ed.GetEntity(peo2);
                    if (psr2.Status != PromptStatus.OK)
                        return;


                    using (Transaction tr = db.TransactionManager.StartTransaction())
                    {
                        ObjectId brId = psr.ObjectId;

                        // Open the block reference
                        BlockReference br = (BlockReference)tr.GetObject(brId, OpenMode.ForRead);

                        int att1 = 0;
                        int att2 = 0;

                        //iterate through attributes but break after first
                        foreach (ObjectId attId in br.AttributeCollection)
                        {
                            // Open the attribute reference
                            AttributeReference att1obj = (AttributeReference)tr.GetObject(attId, OpenMode.ForRead);
                            att1 = Convert.ToInt32(att1obj.TextString);

                            break; //break the process at the first attrib
                        }

                        ObjectId brId2 = psr2.ObjectId;

                        // Open the block reference
                        BlockReference br2 = (BlockReference)tr.GetObject(brId2, OpenMode.ForRead);

                        //iterate through attributes but break after first
                        foreach (ObjectId attId2 in br2.AttributeCollection)
                        {
                            // Open the attribute reference
                            AttributeReference att2obj = (AttributeReference)tr.GetObject(attId2, OpenMode.ForRead);
                            att2 = Convert.ToInt32(att2obj.TextString);
                            break; //break the process at the first attrib
                        }

                        //listing the final results

                        var position1 = br.Position;                     
                        var position2 = br2.Position;                                 
                        var distcheck = position1.DistanceTo(position2);                      
                        int diff = Math.Abs(att1 - att2);                        
                        var slopecheck = (diff / distcheck);

                        ed.WriteMessage("\n{0}, Position: {1}", br.Name, position1);
                        ed.WriteMessage("\n{0}, Position: {1}", br2.Name, position2);
                        ed.WriteMessage("\nDistance: {0}", distcheck);
                        ed.WriteMessage("\nDifference: {0}", diff);
                        ed.WriteMessage("\nSlope: {0}", slopecheck);
                    }
                }
            }
            catch (System.Exception e)
            { Application.ShowAlertDialog(String.Format("You Failed Horribly :P\n{0}", e.Message)); }
        }

    }
}&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 22 Feb 2013 10:58:03 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3786993#M51074</guid>
      <dc:creator>brianchapmandesign</dc:creator>
      <dc:date>2013-02-22T10:58:03Z</dc:date>
    </item>
    <item>
      <title>Re : Seeking Advice to Better Routine</title>
      <link>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3787758#M51075</link>
      <description>&lt;P&gt;Contrary to the misformation being spread by one Autodesk employee, &lt;EM&gt;you should &lt;U&gt;&lt;STRONG&gt;never&lt;/STRONG&gt;&lt;/U&gt; Abort transactions that are used for purely read-only operations&lt;/EM&gt;.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Aborting a transaction has massive overhead relative to committing, and since nothing has been modified, there's no undo information to record..&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Also, if by chance you were to acquire input while a transaction was active,and the user panned or zoomed the view, that's a change to the drawing, and aborting the transaction will cause it to be undone, which isn't very nice.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;To demonstrate just how much more overhead aborting a transaction has,&lt;/P&gt;&lt;P&gt;you can try loading and running this:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.ApplicationServices;

namespace Duh
{
   public static class AbortThisCommands
   {
      static int iterations = 1000;

      [CommandMethod( "ABORT_THIS" )]
      public static void AbortThisCommand()
      {
         Document doc = Application.DocumentManager.MdiActiveDocument;

         PromptIntegerOptions peo = new PromptIntegerOptions( "\nIterations: " );
         peo.AllowZero = false;
         peo.AllowNegative = false;
         peo.DefaultValue = iterations;
         peo.UseDefaultValue = true;
         PromptIntegerResult pir = doc.Editor.GetInteger( peo );
         if( pir.Status != PromptStatus.OK )
            return;
         iterations = pir.Value;

         Stopwatch st = Stopwatch.StartNew();
         for( int i = 0; i &amp;lt; iterations; i++ )
         {
            using( Transaction tr = doc.TransactionManager.StartTransaction() )
            {
               BlockTable bt = (BlockTable) tr.GetObject(
                  doc.Database.BlockTableId,
                  OpenMode.ForRead, false, false );
               tr.Abort();
            }
         }
         st.Stop();

         doc.Editor.WriteMessage( "\nTime to abort {0} transactions: {1} ms",
            iterations, st.ElapsedMilliseconds );
         
         st = Stopwatch.StartNew();
         for( int i = 0; i &amp;lt; iterations; i++ )
         {
            using( Transaction tr = doc.TransactionManager.StartTransaction() )
            {
               BlockTable bt = (BlockTable) tr.GetObject(
                  doc.Database.BlockTableId, 
                  OpenMode.ForRead, false, false );
               tr.Commit();
            }
         }
         st.Stop();

         doc.Editor.WriteMessage( "\nTime to commit {0} transactions: {1} ms",
            iterations, st.ElapsedMilliseconds );
      }
   }
}&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 23 Feb 2013 05:36:34 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3787758#M51075</guid>
      <dc:creator>DiningPhilosopher</dc:creator>
      <dc:date>2013-02-23T05:36:34Z</dc:date>
    </item>
    <item>
      <title>Re : Seeking Advice to Better Routine</title>
      <link>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3787785#M51076</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;To add to what DinnerPhilosopher said, rather than starting a transaction at each loop, you'd start a single transaction and make your while loop within it.&lt;/P&gt;&lt;P&gt;As you're doing the same thing with both block selections, you can extract a single method to prompt the user for selecting a block, get the BlockReference object from the selection, check if the selected block has attributes and if the first one can be converted into an integer.&lt;/P&gt;&lt;P&gt;The method would return true if succeeded or false otherwise and set the values of a BlockReference and an integer out parameters.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;        [CommandMethod("BP")]
        public void BPosition()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            try
            {
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    while (true)
                    {
                        BlockReference br1,  br2;
                        int att1, att2;

                        if (!TryGetBlockInfo(ed, "\nSelect first block: ", out br1, out att1))
                            break;

                        if (!TryGetBlockInfo(ed, "\nSelect second block: ", out br2, out att2))
                            break;

                        double distcheck = br1.Position.DistanceTo(br2.Position);
                        int diff = Math.Abs(att1 - att2);

                        ed.WriteMessage(
                            "\n{0}, Position: {1}\n{2}, Position: {3}\nDistance: {4}\nDifference{5}\nSlope: {6}",
                            br1.Name,
                            br1.Position,
                            br2.Name,
                            br2.Position,
                            distcheck,
                            diff,
                            diff / distcheck);
                    }
                    tr.Commit();
                }
            }
            catch (System.Exception e)
            {
                Application.ShowAlertDialog(String.Format("You Failed Horribly :P\n{0}", e.Message));
            }
        }

        /// &amp;lt;summary&amp;gt;
        /// Prompt the user to select a block.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name="ed"&amp;gt;The current Editor.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="message"&amp;gt;The message to display.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="br"&amp;gt;The selected block reference.&amp;lt;/param&amp;gt;
        /// &amp;lt;param name="value"&amp;gt;The block first attribute value.&amp;lt;/param&amp;gt;
        /// &amp;lt;returns&amp;gt;True if the user select a block reference wich first attribute value is an integer, false otherwise.&amp;lt;/returns&amp;gt;
        private bool TryGetBlockInfo(Editor ed, string message, out BlockReference br, out int value)
        {
            br = null;
            value = -1;

            PromptEntityOptions peo = new PromptEntityOptions(message);
            peo.SetRejectMessage("\nMust be a block.");
            peo.AddAllowedClass(typeof(BlockReference), false);
            PromptEntityResult per = ed.GetEntity(peo);

            if (per.Status == PromptStatus.OK)
                return false;

            br = (BlockReference)per.ObjectId.GetObject(OpenMode.ForRead);
            if (br.AttributeCollection.Count == 0)
                return false;

            AttributeReference attRef =
                (AttributeReference)br.AttributeCollection[0].GetObject(OpenMode.ForRead);
            if (int.TryParse(attRef.TextString, out value))
                return true;

            return false;
        }&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 23 Feb 2013 11:35:28 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3787785#M51076</guid>
      <dc:creator>_gile</dc:creator>
      <dc:date>2013-02-23T11:35:28Z</dc:date>
    </item>
    <item>
      <title>Re : Seeking Advice to Better Routine</title>
      <link>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3787789#M51077</link>
      <description>&lt;P&gt;That's awesome Gilles. Very helpful. Thank you!&lt;/P&gt;</description>
      <pubDate>Sat, 23 Feb 2013 11:58:40 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3787789#M51077</guid>
      <dc:creator>brianchapmandesign</dc:creator>
      <dc:date>2013-02-23T11:58:40Z</dc:date>
    </item>
    <item>
      <title>Re : Seeking Advice to Better Routine</title>
      <link>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3787811#M51078</link>
      <description>&lt;P&gt;Thanks.&lt;/P&gt;&lt;P&gt;There's a typo in the upper code:&lt;/P&gt;&lt;P&gt;repace:&lt;/P&gt;&lt;P&gt;if (per.Status == PromptStatus.OK)&lt;/P&gt;&lt;P&gt;with:&lt;/P&gt;&lt;P&gt;if (per.Status != promptStatus.OK)&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Another way would be creating a little class (called BlockInfo here) to get the required infos. In this example, I used the ObjectId.Open() method rather than using a Transaction to get the block reference and its first attribute. In case of incorrect inputs (none attribute or not integer value) an exception is thrown.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;        [CommandMethod("BI")]
        public void GetBlockInfos()
        {
            try
            {
                Editor ed = AcAp.DocumentManager.MdiActiveDocument.Editor;
                while (true)
                {
                    BlockInfo bi1 = BlockInfo.Select(ed, "\nSelect first block: ");
                    if (bi1 == null)
                        break;
                    BlockInfo bi2 = BlockInfo.Select(ed, "\nSelect second block: ");
                    if (bi2 == null)
                        break;
                    ed.WriteMessage(
                        "\n{0}, Position: {1}\n{2}, Position: {3}\nDistance: {4}\nDifference: {5}\nSlope: {6}",
                        bi1.Name,
                        bi1.Position,
                        bi2.Name,
                        bi2.Position,
                        bi1.DistanceTo(bi2),
                        bi1.DifferenceTo(bi2),
                        bi1.SlopeTo(bi2));
                }
            }
            catch(System.Exception e)
            {
                Application.ShowAlertDialog(String.Format("You Failed Horribly :P\n{0}", e.Message));
            }
        }

        class BlockInfo
        {
            // private field
            private int value;

            // constructor
            public BlockInfo(ObjectId id)
            {
                using (BlockReference br = (BlockReference)id.Open(OpenMode.ForRead))
                {
                    if (br.AttributeCollection.Count == 0)
                        throw new ArgumentException("None attribute");
                    using (AttributeReference attRef =
                        (AttributeReference)br.AttributeCollection[0].Open(OpenMode.ForRead))
                    {
                        if (!int.TryParse(attRef.TextString, out value))
                            throw new ArgumentException("Not an integer");
                    }
                    Name = br.Name;
                    Position = br.Position;
                }
            }

            // properties
            public Point3d Position { get; private set; }

            public string Name { get; private set; }

            public int AttValue { get { return value; } }

            // public instance methods
            public double DistanceTo(BlockInfo other)
            {
                return this.Position.DistanceTo(other.Position);
            }

            public int DifferenceTo(BlockInfo other)
            {
                return Math.Abs(value - other.AttValue);
            }

            public double SlopeTo(BlockInfo other)
            {
                return this.DifferenceTo(other) / this.DistanceTo(other);
            }

            // public static method
            public static BlockInfo Select(Editor ed, string message)
            {
                PromptEntityOptions peo = new PromptEntityOptions(message);
                peo.SetRejectMessage("\nMust be a block.");
                peo.AddAllowedClass(typeof(BlockReference), false);
                PromptEntityResult per = ed.GetEntity(peo);
                if (per.Status != PromptStatus.OK)
                    return null;
                return new BlockInfo(per.ObjectId);
            }
        }&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 23 Feb 2013 13:08:06 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3787811#M51078</guid>
      <dc:creator>_gile</dc:creator>
      <dc:date>2013-02-23T13:08:06Z</dc:date>
    </item>
    <item>
      <title>Re : Seeking Advice to Better Routine</title>
      <link>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3787951#M51079</link>
      <description>&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://forums.autodesk.com/t5/user/viewprofilepage/user-id/109424"&gt;@_gile&lt;/a&gt; wrote:&lt;BR /&gt;&lt;P&gt;Hi,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;To add to what DinnerPhilosopher said, rather than starting a transaction at each loop, you'd start a single transaction and make your while loop within it.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;Hi Gile.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The test code was designed to simulate how transactions might be used in other methods that may have to be called many times in a loop. In some cases, they may be reusable methods that may not assume a transaction is already running. &amp;nbsp;The code wasn't an example of how to use transactions, as you've noted, it would serve no purpose to start and end one on each loop iteration.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;</description>
      <pubDate>Sat, 23 Feb 2013 19:17:00 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3787951#M51079</guid>
      <dc:creator>DiningPhilosopher</dc:creator>
      <dc:date>2013-02-23T19:17:00Z</dc:date>
    </item>
    <item>
      <title>Re : Seeking Advice to Better Routine</title>
      <link>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3787980#M51080</link>
      <description>&lt;P&gt;Yes, I understand, Tony, I wanted to purpose the OP to use a single transaction AND commit it.&lt;/P&gt;</description>
      <pubDate>Sat, 23 Feb 2013 20:44:57 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3787980#M51080</guid>
      <dc:creator>_gile</dc:creator>
      <dc:date>2013-02-23T20:44:57Z</dc:date>
    </item>
    <item>
      <title>Re : Seeking Advice to Better Routine</title>
      <link>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3788021#M51081</link>
      <description>&lt;P&gt;Thank you gentleman!&amp;nbsp; You've been very helpful &lt;img id="smileyhappy" class="emoticon emoticon-smileyhappy" src="https://forums.autodesk.com/i/smilies/16x16_smiley-happy.png" alt="Smiley Happy" title="Smiley Happy" /&gt;&lt;/P&gt;</description>
      <pubDate>Sun, 24 Feb 2013 00:27:59 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/net-forum/seeking-advice-to-better-routine/m-p/3788021#M51081</guid>
      <dc:creator>brianchapmandesign</dc:creator>
      <dc:date>2013-02-24T00:27:59Z</dc:date>
    </item>
  </channel>
</rss>

